Monday, 30 April 2012

Jmeter Sampler Client

Download  latest Jmeter binaries  and install as for instruction given.

You can use some Java development tools like eclipse for developing client program.
i am just creating simple sample program using eclipse because it provide lot of utility like auto compile, create jar etc.

Lets start with creating simple java class JmeterTestClient.java inside jmeter.sampler either by implementing JavaSamplerClient(org.apache.jmeter.protocol.java.sampler.JavaSamplerClient) or extending AbstractJavaSamplerClient(org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient)

you need ApacheJMeter_java.jar ApacheJMeter_core.jar for compilation only. You can find both jars at <<Installation_dir>>\jakarta-jmeter-2.4\lib\ext

When possible, Java tests should extend AbstractJavaSamplerClient rather than implementing JavaSamplerClient directly. This should protect your tests from future changes to the interface. While it may be necessary to make changes to the JavaSamplerClient interface from time to time (therefore requiring changes to any implementations of this interface), we intend to make this abstract class provide reasonable default implementations of any new methods so that subclasses do not necessarily need to be updated for new versions. Implementing JavaSamplerClient directly will continue to be supported for cases where extending this class is not possible (for example, when the client class is already a subclass of some other class).

This interface defines the interactions between the JavaSampler and external Java programs which can be executed by JMeter. Any Java class which wants to be executed as a JMeter test must implement this interface (either directly or indirectly through AbstractJavaSamplerClient).
JMeter will create one instance of a JavaSamplerClient implementation for each user/thread in the test. Additional instances may be created for internal use by JMeter (for example, to find out what parameters are supported by the client).
When the test is started, setupTest() will be called on each thread's JavaSamplerClient instance to initialize the client. Then runTest() will be called for each iteration of the test. Finally, teardownTest() will be called to allow the client to do any necessary clean-up

Compile the above java file and export as jar and put inside <<Installation_dir>>\jakarta-jmeter-2.4\lib\ext   
start jmeter , select testplan creat new thread group and select thread group add java request sampler . select JmeterTestClient  from classname drop down . save your test plan and run.
in my example i printed some text are you can see in console ,You can set loop count in thread group.
The sample code is.



package jmeter.sampler;


import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;


public class JmeterTestClient implements JavaSamplerClient {
int count;


@Override
public Arguments getDefaultParameters() {
count = 10;
System.out.println("inside default");
return null;
}


@Override
public SampleResult runTest(JavaSamplerContext arg0) {
System.out.println("Inside Run test:" + count++);
return null;
}


@Override
public void setupTest(JavaSamplerContext arg0) {
count++;
System.out.println("inside Setup");
}


@Override
public void teardownTest(JavaSamplerContext arg0) {
System.out.println("inside tear Down:" + count);
}


}

Thursday, 26 April 2012

Understanding how EJB calls operate in WebSphere Application Server V6.1

Summary:  Many applications use Enterprise JavaBeans™ (EJB) deployed in an IBM® WebSphere ® Application Server EJB container. Communication to these EJB components requires the use of concepts like Internet Inter-ORB Protocol (IIOP) communication, JNDI look-ups, and workload management. This interaction can be complex and is often a black box for many WebSphere users. This article provides a basic understanding of how EJB communication works in the context of WebSphere Application Server. Communication into and out of the ORB is addressed, along with the definitions of basic call patterns and components involved in making calls to EJB components deployed in the EJB container. A basic understanding of J2EE™ principles and general administrative knowledge of WebSphere Application Server is assumed. 



Introduction
For many WebSphere users, EJB communications are a black box. That is, we understand that calling method 'X' will return the desired result from the EJB business logic. Under normal operating conditions, this knowledge may be sufficient as it is not usually necessary to understand the inner workings of the ORB. However, when performance problems or load balancing issues arise, in-depth knowledge of the ORB can greatly enhance the the problem determination effort and reduce time to resolution. As with any WebSphere component, understanding the mechanism of operation for the ORB and its related communication protocols can yield further expertise when troubleshooting it.
The ORB
The ORB is the central part of CORBA, or Common Object Request Broker Architecture, which aims to make remote objects usable like local objects in object-oriented, distributed applications. In addition, ORB lets these objects communicate with each other regardless of the specific platforms, techniques, and languages that are used to implement those objects.
CORBA is an open, vendor-neutral specification for distributed computing created by the Object Management Group (OMG), a consortium of over 600 software vendors and other companies promoting open, standard interfaces. CORBA and its Interface Definition Language (IDL) provides a common format for representing an object that can be distributed to applications written in Java™, C, C++, and other languages and running on different operating systems and machines.
The ORB (Object Request Broker) plays an integral part in the application server runtime. The ORB is implemented as part of the Java Virtual Machine (JVM). IBM WebSphere Application Server includes additional code (generally referred to as the extension ORB) that manages the ORB instance, and also provides the plug-in framework for object services (such as security). This IBM ORB implementation is not the same as the Sun™ ORB; the code base is different altogether. It is the foundation on which the EJB container depends to broker communication for Java Remote Method Invocation (RMI) interactions. RMI is Java’s traditional method of performing remote communications and uses a non-standardized protocol, named Java Remote Method Protocol (JRMP), to communicate between Java objects. At the most basic level, RMI is just Java’s object-oriented version of Remote Procedure Calls (RPCs). WebSphere Application Server uses the ORB to facilitate client/server RMI communication, as well as to communicate between components.
The ORB manages inbound and outbound requests for remote Java objects, like EJB components. ORB provides a framework for clients to locate EJBs on the server and invoke operations on those as if they were local. (This concept is referred to as local-remote transparency.) The relationship of the ORB with the EJB container can be described with Figure 1.

Figure 1. ORB and the EJB container
Figure 1.  ORB and the EJB container 
Inter-ORB communication
Communication between ORBs is accomplished via the IIOP, which is a concrete implementation of the General Inter-Orb Protocol (GIOP) abstract reference specification. The Interoperable Object Reference (IOR) is simply a string representation of the CORBA or RMI-IIOP object reference in a format that ORBs can understand. You can think of this as a normal Java object reference used in everyday coding. IIOP maps GIOP to the TCP/IP communication stack.
The GIOP protocol specifies several different types of messages, such as request messages, reply messages, locate request messages, locate reply messages, and fragment messages. The request and reply message types are self-explanatory, as they deal with the request and response interaction between client and server applications. The locate request and fragment message types might not be as familiar to you unless you have needed to read through GIOP tracing to solve a problem:
  • The locate request message type is used to verify that the ORB understands and houses the requested remote object. If the ORB does not know the object requested in the locate request message, it will attempt to provide details (for example, an OBJECT_FORWARD which points to a server that does house the object) on where the client can find the requested object.
  • The fragment message is a continuation of the previous message delivered to the ORB.
Processing large GIOP messages can cause problems for the ORB. GIOP messages can be fragmented into manageable pieces for easier and faster processing. Custom properties can be set in WebSphere Application Server that specify the exact size in which to fragment a message (or whether or not to fragment messages at all). By default, WebSphere Application Server will fragment GIOP messages at 1024 bytes.
In the most basic of interaction scenarios, the client and the server ORBs communicate directly with each other to satisfy application requests for remote resources. However, in more complex interactions, such as clustered servers with workload management features, processes other than the client and server can become involved (for the purpose of this article) in the NodeAgent process.
Each application server contains an ORB that listens for incoming requests. The ORB has three or more ports that are associated with it: the ORB listener port, the bootstrap port, and the security ports. The ORB listener port is the actual port that the ORB listens on for incoming IIOP requests if ORB security is not enabled. The bootstrap port is always an active, well-advertised port, and always returns an indirect IOR containing the secured and unsecured listener ports. A well-constructed client should always bootstrap to the server in which the remote resource resides (or to a multiple host provider URL that points to the cluster if the resource resides in a cluster). There are three other ports associated with the ORB and security: the CSIv2 Client Authentication SSL port, the CSIv2 SSL port, and the SAS SSL port. (Details of these ports is beyond the scope of this article and will not be covered here.) ORB listener ports are, by default, dynamically determined from the platform’s ephemeral port range at run time. However, these ports can be set to a specific static port for various reasons, such as firewall rules, business policies, and so on.
When an ORB client requests a reference to a remote object, the remote ORB will reply with an Interoperable Object Reference (IOR), which is simply a string representation of the CORBA or RMI-IIOP object reference in a format that ORBs can understand, and at the very basic level contains host and port information for the server on which the object can be found. The IOR can be thought of as a typical Java object reference used in everyday coding.

How is the NodeAgent involved?
First, the NodeAgent process is only involved in an ORB transaction in the WebSphere Application Server Network Deployment product; it is not present in the base application server offering. The NodeAgent process houses a service called the location service daemon, which enables application servers to register their services and remote objects by providing the daemon with direct IORs pointing to the said application server. Later, when a locate request comes into the location service daemon, it uses the registration information to provide a direct IOR back to a client that points to the registered application server’s ORB listener ports. This registration/IOR information could be thought of as a sort of routing table that is used by the daemon to locate EJBs and other resources found on the various application servers managed by a particular NodeAgent.
Before a managed application server can start properly, a NodeAgent must be available locally on the node. It is possible to configure the application servers such that the dependency on the NodeAgent process (actually the location service daemon service) is gone. However, this setup involves carrying out static routing for IIOP requests, and thus WebSphere Application Server’s workload management services would be nullified. This static routing setup should be avoided unless truly required. (Consult IBM Support before making this assessment on your own.)
In the event that the NodeAgent process dies or must be taken down or restarted during the operation of an application server on the same node with EJBs deployed on it, exceptions might be thrown in the server logs once the NodeAgent is unavailable. These messages are due to the fact that, once the NodeAgent is removed from the process, the IIOP communication is altered in a way that prevents both ORBs (client and server) from communicating correctly. However, as long as clients already have direct IORs to their desired servers, have already created their EJBHome object, and are making remote calls to that EJB, the NodeAgent is unlikely to be involved in the IIOP communication after that point.
Ideally, incoming locate requests to the location service daemon for EJB-related objects will not come in until all the application servers on a particular node have completed their registration with the location service daemon on the NodeAgent. When locate requests come in for objects on servers that have not yet registered or are temporarily down (and hence no longer registered), a CORBA.OBJECT_NOT_EXIST exception will be returned to the client. In this case, the status of the application server needs to be checked to ensure they are all up and running and have registered with the location service daemon.
Understanding the ORB call pattern
In order for high level application functionality (like EJB components) to work, inter-ORB communication must occur. There are two basic scenarios that we can observe:
  • A standalone application server (WebSphere Application Server, not Network Deployment)
  • A clustered application server in a WebSphere Application Server Network Deployment environment.
The next sections describe these scenarios.
WebSphere Application Server base instance
In this scenario, the EJB component and its client are contained in the separate application servers. The client code to make the call might look like this:

Listing 1
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming
.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL,"corbaloc::isador:2810");
Context ctx = new InitialContext(env);
TestEJBHome home = (TestEJBHome)
PortableRemoteObject.narrow(ctx.lookup("ejb/ejbs/TestEJBHome"),
 TestEJBHome.class);
TestEJB bean = home.create();
            

The code in bold text are the lines that result in remote ORB calls. When put into motion, you can follow the events in Figure 2, where the events are listed, in sequence, from top to bottom.

Figure 2. ORB event calls in base instance
Figure 2. ORB event calls in base instance 
Figure 2 is divided into three parts, each part corresponding to a portion of the Java code in Listing 1:
  • The top section contains the events that result from the InitialContext creation on the client.
  • The middle section contains the events that result from the InitialContext.lookup() method.
  • The bottom section contains the events that result from the creation of the EJB instance.
From this diagram, you can see that the process of obtaining an initial context from the server involves sending a locate request message to the ORB (client and server ORB are the same here) on the ORB’s bootstrap port. The resulting reply message contains a direct IOR (with host and TCP/IP and SSL port information) that points the client to the server containing the requested object. Next, the client issues another locate request message, but this time to the ORB’s listener port. After this, the client requests some information from the ORB to establish an initial context.
After the InitialContext value has been obtained, the client code then does a lookup in the JNDI namespace to determine how to get a reference to the desired remote object (WLMTestEJB). To accomplish this, the client issues yet another locate request aimed at the ORB’s listener port. The ORB replies back to the client via a locate reply message stating that the object is indeed contained locally. In response to the locate reply, the client then requests that the ORB resolve the object and return a reference to the client. Under the covers, this entails the ORB using a tie class to connect the real Java object with the request that came to the ORB. When the client has the reference, it uses a “narrow” call to marshal the generic object returned from the ORB into the desired object type.
The last thing the code does is create an instance of the remote EJB. To complete the process, the client issues a locate request to the remote ORB, to which the ORB replies with a locate reply stating that the object is present. Finally, the client then invokes the create() method on the remote object. When the process is complete in the ORB, the ORB marshals the response back to the client. All data that goes into or leaves the ORB (like method parameters and method return values) are serialized and deserialized using a format called common data representation (CDR). As such, all values passed into the ORB must implement the serializable interface.
The locate request messages used in this base application server scenario are simple locate requests that are processed by the ORB itself. This is different from the next scenario because the location service daemon plug-in (attached to the ORB instance) handles messages responding to the locate requests.
WebSphere Application Server Network Deployment clustered instance
In this scenario, the major difference is that the client ORB and server ORB will almost always be two different JVM instances, often located on completely separate hosts. The process will appear much the same, but you will notice the involvement of the location service daemon server contained in the NodeAgent. Listing 2 shows the code involved to make the call.

Listing 2
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming
.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL,"corbaloc::boris:9811,:natasha
:9812");
Context ctx = new InitialContext(env);
TestEJBHome home = (TestEJBHome)
PortableRemoteObject.narrow(ctx.lookup("ejb/ejbs/TestEJBHome"),
 TestEJBHome.class);
TestEJB bean = home.create();
            

The code only changed from the previous example in only one place: the values placed in the PROVIDER_URL key of the environment Hashtable object. In this case, the developer included multiple corbaloc URLs, each of which points to a separate server’s bootstrap port. This change introduces some fault tolerance and failover to the process as the code now has two paths from which the InitialContext object can be obtained. As in the previous scenario, the code in bold text is responsible for generating the remote ORB requests. Figure 3 illustrates the sequence of events for this scenario, formatted the same as the previous example.

Figure 3. ORB event calls in clustered instance
Figure 3. ORB event calls in clustered instance 
For the creation of the InitialContext object in the top section, there are no obvious differences between this scenario and the first one. However, with the addition of WebSphere Application Server workload management in the picture, there are slight differences.
First, during the creation of the InitialContext (top section), a list of IORs that point to each of the cell’s location service daemon clusters are prepared and returned to the client ORB during the getProperties() portion of the conversation. When the client ORB makes further calls to the server ORB, the workload management plug-in on the client side iterates over the list and issues a resolve_complete_info request. This first request is routed to the location service daemon service in the NodeAgent (shown as the first call in the middle section), where the desired cluster data is sent back to the client in the form of a direct IOR pointing to the destination server.
In the bottom section of the diagram, you can see that the locate request message issued in the first scenario is not needed and the create() method is invoked instead, immediately without having to process the additional locate request because workload management has already “located” an appropriate application server.
Summary
This article defined the ORB and how it provides the application server runtime with vital functionality needed to service clients making remote requests to an EJB server. The high level sequence of events that make up inter-ORB communications was also explained, along with the role that the NodeAgent plays in the part of ORB communication between clients and servers.
There is much more information available on these topics. If you wish to continue your reading, you might want to look into these subjects:
  • GIOP protocol
  • Problem determination for the ORB/EJB container
  • RMI over IIOP
  • Java Naming and Directory Interface (JNDI)
  • EJB clustering
  • WebSphere workload management (WLM)
  • CORBA and the OMG.
Acknowledgements
The authors extend their thanks to Paul Bullis and Claudia Barrett for providing guidance and clarification on the topics discussed in this article.


Wednesday, 18 April 2012

FTP Configuration on a Firewall


This page gives a detailed description on what TCP activity goes on during a FTP session. If you are looking for answers to connection problems caused by routers and firewalls, you should look here. 

Whenever an FTP client creates a connection to an FTP server at port 21, and starts to request data, the server will create a data link back from it's own port 20 to the port specified in the original connection by the client through a PORT command (non-passive connection, the most usual).
However, the client can instead of sending a PORT command, send a PASV command, which means the server is to send a message back to the client with a listening port number, so the client can itself create the data link (passive connection).
This gives in all 4 different combinations to take into account when configuring a port oriented firewall:
1) FTP server doing non-passive connection.
2) FTP server doing passive connection.
3) FTP client doing non-passive connection.
4) FTP client doing passive connection.
The easy way is to simply allow FTP servers and clients unlimited access through your firewall, but if you like to limit their access to "known" ports, you have to understand the 4 different scenarios.
1) The FTP server should be allowed to accept TCP connections to port 21, and to make TCP connections from port 20 to any (remote ephemeral) port.
2) The FTP server should be allowed to accept TCP connections to port 21, AND to accept TCP connections to any ephemeral port as well!
3) The FTP client should be allowed to make TCP connections to port 21, and to accept TCP connections from port 20 to any ephemeral port.
4) The FTP client should be allowed to make TCP connections to port 21, and to make TCP connections to any other (remote ephemeral) port as well!
Schematically:
Non Passive
Passive
An ephemeral (or dynamic) port is a temporary, short lived port, assigned to the application by the IP stack, taken from a specified pool. Mike Gleason has a wonderful page describing this principle in relation to FTP and firewalls as well. The range of ports used as ephemeral ports is both rather large, and can vary from system to system, both adding to the complexity of configuring a firewall correctly. Whenever an application makes a TCP connection, it is (usually) assigned a port by the IP stack as a "return address", meaning a TCP connection can have any port as its origin, and that is not a problem for firewalls at all, as they mostly check the destination port to figure out what to do. When FTP is involved, ephemeral ports are used as destination ports too, and that complicates the matter drastically.

Server Side

If you have an FTP server, you should configure both case 1) and 2). 1) is easy enough, it is case 2) that needs consideration. It should be obvious that you trust your FTP server not to do any hanky panky, so allowing it to accept TCP connections to any ephemeral port should NOT be a problem. (In windows, the ephemeral port range is by default 1024-5000, but the upper range can be changed.)
Sometimes, the FTP server can itself be assigned a range to use for PASV connections, as is the case with Cerberus that I am using. This makes it possible to define a range of ports that are not too difficult to configure in the firewall without any problems. When configuring this range, you must be carefull not to choose too narrow a range. First of all, several ports can be used by the same connection, second, you should be able to handle several clients at the same time, and third, an ephemeral port has a rather long latency period (minutes), before Windows allows that port to be reused, so you can very quickly run out of ports! Make sure you select a port range of at least several hundred ports. If you are having problems downloading and uploading to the server, but not connecting, this range is the first thing to check, if you are sure your firewall is configured correctly.
If your server is behind a router, you will have to configure the router as well. Note that routing port 21 is not enough, the chosen range of ports for PASV connections must also be routed correctly. Of course, all outgoing connections must be possible as well.

Client Side

You probably also want to be able to act as an FTP client. This time, both case 3) and 4) pose problems: In case 3), you want to allow any incoming connection to your FTP client from port 20. This sounds acceptable, but in some cases could be very dangerous, as we shall see in a moment. In case 4), the FTP client should be allowed to do connections to any port (returned from an FTP server), and this also sounds acceptable, but again, it may not be, as we shall see.
There are 3 basic cases, that need to be configured.
a) You use a simple FTP client program.
b) You use a browser like Internet Explorer as FTP client.
c) You connect through a proxy server running ProxyPlus, for instance, like I am myself.
In case a), it is not a problem to allow it to accept connections on any port from port 20. There is of course a risc of a hacking attempt from port 20, but it requires a very lucky punch to hit your port while it is active, and even more luck to actually fool the FTP program, so I consider that risc remote indeed. But you also need to allow the client to make TCP connections to any other port. Again, we must assume you trust your FTP client, so this should not be a problem either.
Case b), and the trouble begins... Again, the chance of someone finding an open port waiting for connections from port 20 is remote (case 3), but do you trust the Internet Explorer or any other browser to allow it to connect to just any port (case 4)? Especially in these days, when browsers are running ActiveX components and scripts of all kinds. You might argue, that any malicious script or component would of course choose to report back on port 80, as this port is of course always open for the browser to connect to. Still, I don't like the idea, so think about it before allowing your browser to do passive connection. (In Internet Explorer 6 SP1, this can be configured in the Options dialog, Advanced, Browsing.) Lucky for me, I am using ProxyPlus as a proxy, so my browser cannot connect to just any machine, and it is not a big problem with Kerio and Tiny personal firewall to configure it to ask for accept on new connection types. That way I can accept the connection explicitly, whenever I need to do FTP, which is not often, without giving the firewall any definite rule.
Case c) is the really difficult one! The proxy server need to be acting as an FTP server to the clients, but that is not a big problem as clients have known addresses, so these addresses can just be given the required permissions. But on the outside, the job is not all that simple.
Case 3) requires it to accept connections on any port from port 20, but as my proxy server has a lot of other ports open for other cases, the chance of a hacking attempt against it from a port 20 is much higher, opposed to the case of the client, which only had "stupid" ports open, waiting for connections from port 20. The ProxyPlus application is also offering a LOT of other services that could be abused. Of course, I have configured my proxy to only perform services when requested from "secure" clients, but I don't like the idea of just opening all ports! Also, only the ephemeral port range is relevant, but that range does indeed include ports actually used for some of the proxy server's actual services.
One way to do it is to create rules DISALLOWING connections from the outside to these sensitive ports BEFORE the rule allowing connections to any ephemeral port. Another way is to reconfigure the proxy server's service ports to fall outside the ephemeral port range, so the dangerous rule allowing connections does not interfere with the real service ports.
If you are behind a router, you can choose to route the entire ephemeral port range back to your client machine, or you can choose to do PASV FTP connections, which does not require any odd incoming ports open, but only outgoing connections.
I hope this discussion has given you enough information to decide for yourself how to do it.

Getting started with iptables in Linux


Linux machines are known to be pretty secure. Studies have shown that Linux has been designed in a secure manner. Yet, despite all the security features that come bundled with a Linux installation, you need to configure these features correctly to make them work for you. I’ll guide you through the process of setting up of one of the tools that help secure your machine – the firewall. We will use the iptables firewall for this exercise. I am assuming that you are using a server running Red Hat Enterprise Linux 4 or similar. However, most of the steps should work fine on other Linux distributions as well. In this article we will setup a firewall on a Linux server running the Apache Web Server, FTP, and SSH.
Let us first see what ports these applications use and which of them need to have a port open on the firewall.
The Apache web server runs on port 80 by default. Apache is going to server all our web content on this port, therefore we need to keep this port open on the firewall. The SSH service runs on port 22. We need to be able to remotely connect to our server to work, so we keep it open. FTP runs on port 21 and it too needs the port to be open to communication.
Next, make sure you have iptables installed. Run this command as the root user:
rpm -qa | grep iptables
If you have iptables installed the system should give you the version of iptables you have installed. In case you don’t you can try something like the following to get it and start it:
yum install iptables
/etc/init.d/iptables start
To check what kind of configuration iptables is currently running with:
iptables –list
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
This command will list out all the firewall rules that have been set currently. I will proceed with the assumption that you do not have any firewall rules in your iptables configuration. Let’s now configure the firewall to allow open communication on the ports 80 for your web server, 22 for SSH, and port 21 for FTP. We’ll also make sure that we block communication to any port other than specified.
Here’s a firewall script configuration script. Create a new file and call it iptable-firewall.sh. Copy the following text into it:
#!/bin/sh
ANY=”0/0″
OPEN_PORTS=”21 22 80″
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# Flush (-F) all specific rules
iptables -F INPUT
iptables -F FORWARD
iptables -F OUTPUT
for port in $OPEN_PORTS
do
iptables -A INPUT -i eth0 -p tcp -s $ANY -d $ANY –destination-port $port –syn -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -s $ANY -d $ANY –destination-port $port –syn -j ACCEPT
done
iptables -A INPUT -i eth1 -p icmp -s $ANY -d $ANY -j ACCEPT
#Allow any related/established connections
iptables -A INPUT -i eth0 -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i eth1 -m state –state ESTABLISHED,RELATED -j ACCEPT
#Kill everything else
iptables -A INPUT -i eth0 -j DROP
iptables -A INPUT -i eth1 -j DROP
#write for boot
iptables-save > /etc/sysconfig/iptables
Now save the above file, grant it executable permissions and then run it:
chmod +x iptable-firewall.sh
./iptable-firewall.sh
Now check your firewall rules:
iptables –list
All your firewall rules should now be set. Your server is now secure. To make any modification or additions to this set of rules, edit the line where the OPEN_PORTSparameter is defined and add or remove ports form the list. Remember to run the script again after making any changes to it.

Linux Firewalls Using iptables


Introduction

Network security is a primary consideration in any decision to host a website as the threats are becoming more widespread and persistent every day. One means of providing additional protection is to invest in a firewall. Though prices are always falling, in some cases you may be able to create a comparable unit using the Linux iptables package on an existing server for little or no additional expenditure.

This chapter shows how to convert a Linux server into:
A firewall while simultaneously being your home website's mail, web and DNS server.
A router that will use NAT and port forwarding to both protect your home network and have another web server on your home network while sharing the public IP address of your firewall.
Creating an iptables firewall script requires many steps, but with the aid of the sample tutorials, you should be able to complete a configuration relatively quickly.


What Is iptables?




Originally, the most popular firewall/NAT package running on Linux was ipchains, but it had a number of shortcomings. To rectify this, the Netfilter organization decided to create a new product called iptables, giving it such improvements as:
  • Better integration with the Linux kernel with the capability of loading iptables-specific kernel modules designed for improved speed and reliability.
  • Stateful packet inspection. This means that the firewall keeps track of each connection passing through it and in certain cases will view the contents of data flows in an attempt to anticipate the next action of certain protocols. This is an important feature in the support of active FTP and DNS, as well as many other network services.
  • Filtering packets based on a MAC address and the values of the flags in the TCP header. This is helpful in preventing attacks using malformed packets and in restricting access from locally attached servers to other networks in spite of their IP addresses.
  • System logging that provides the option of adjusting the level of detail of the reporting.
  • Better network address translation.
  • Support for transparent integration with such Web proxy programs as Squid.
  • A rate limiting feature that helps iptables block some types of denial of service (DoS) attacks.
Considered a faster and more secure alternative to ipchains, iptables has become the default firewall package installed under RedHat and Fedora Linux.

Download And Install The Iptables Package

Before you begin, you need to make sure that the iptables software RPM is installed. (See Chapter 6, "Installing Linux Software", if you need a refresher.) When searching for the RPMs, remember that the filename usually starts with the software package name by a version number, as in iptables-1.2.9-1.0.i386.rpm.

How To Start iptables

You can start, stop, and restart iptables after booting by using the commands:
[root@bigboy tmp]# service iptables start
[root@bigboy tmp]# service iptables stop
[root@bigboy tmp]# service iptables restart
To get iptables configured to start at boot, use the chkconfig command:.
[root@bigboy tmp]# chkconfig iptables on

Determining The Status of iptables

You can determine whether iptables is running or not via the service iptables status command. Fedora Core will give a simple status message. For example
[root@bigboy tmp]# service iptables status
Firewall is stopped.
[root@bigboy tmp]#

Packet Processing In iptables

All packets inspected by iptables pass through a sequence of built-in tables (queues) for processing. Each of these queues is dedicated to a particular type of packet activity and is controlled by an associated packet transformation/filtering chain.
There are three tables in total. The first is the mangle table which is responsible for the alteration of quality of service bits in the TCP header. This is hardly used in a home or SOHO environment.
The second table is the filter queue which is responsible for packet filtering. It has three built-in chains in which you can place your firewall policy rules. These are the:
  • Forward chain: Filters packets to servers protected by the firewall.
  • Input chain: Filters packets destined for the firewall.
  • Output chain: Filters packets originating from the firewall.
The third table is the nat queue which is responsible for network address translation. It has two built-in chains; these are:
  • Pre-routing chain: NATs packets when the destination address of the packet needs to be changed.
  • Post-routing chain: NATs packets when the source address of the packet needs to be changed



Table 14-1 Processing For Packets Routed By The Firewall

Queue TypeQueue FunctionPacket Transformation Chain in QueueChain Function
FilterPacket filtering
FORWARD
Filters packets to servers accessible by another NIC on the firewall.
INPUT
Filters packets destined to the firewall.
OUTPUT
Filters packets originating from the firewall
NatNetwork Address Translation
PREROUTING
Address translation occurs before routing. Facilitates the transformation of the destination IP address to be compatible with the firewall's routing table. Used with NAT of the destination IP address, also known as destination NAT or DNAT.
POSTROUTING
Address translation occurs after routing. This implies that there was no need to modify the destination IP address of the packet as in pre-routing. Used with NAT of the source IP address using either one-to-one or many-to-one NAT. This is known as source NAT, or SNAT.
OUTPUT
Network address translation for packets generated by the firewall. (Rarely used in SOHO environments)
MangleTCP header modification
PREROUTING
POSTROUTING
OUTPUT
INPUT
FORWARD
Modification of the TCP packet quality of service bits before routing occurs. (Rarely used in SOHO environments)

You need to specify the table and the chain for each firewall rule you create. There is an exception: Most rules are related to filtering, so iptables assumes that any chain that's defined without an associated table will be a part of the filter table. The filter table is therefore the default.
To help make this clearer, take a look at the way packets are handled by iptables. In Figure 14.1 a TCP packet from the Internet arrives at the firewall's interface on Network A to create a data connection.
The packet is first examined by your rules in the mangle table's PREROUTING chain, if any. It is then inspected by the rules in the nat table's PREROUTING chain to see whether the packet requires DNAT. It is then routed.
If the packet is destined for a protected network, then it is filtered by the rules in the FORWARD chain of the filter table and, if necessary, the packet undergoes SNAT in the POSTROUTING chain before arriving at Network B. When the destination server decides to reply, the packet undergoes the same sequence of steps. Both the FORWARD and POSTROUTING chains may be configured to implement quality of service (QoS) features in their mangle tables, but this is not usually done in SOHO environments.
If the packet is destined for the firewall itself, then it passes through the mangle table of the INPUT chain, if configured, before being filtered by the rules in the INPUT chain of the filter table before. If it successfully passes these tests then it is processed by the intended application on the firewall.
At some point, the firewall needs to reply. This reply is routed and inspected by the rules in the OUTPUT chain of the mangle table, if any. Next, the rules in the OUTPUT chain of the nat table determine whether DNAT is required and the rules in the OUTPUT chain of the filter table are then inspected to help restrict unauthorized packets. Finally, before the packet is sent back to the Internet, SNAT and QoS mangling is done by the POSTROUTING chain

Figure 14-1 Iptables Packet Flow Diagram

Iptables.gif
It is now time to discuss the ways in which you add rules to these chains.

Targets And Jumps

Each firewall rule inspects each IP packet and then tries to identify it as the target of some sort of operation. Once a target is identified, the packet needs to jump over to it for further processing. Table 14.2 lists the built-in targets that iptables uses.

Table 14-2 Descriptions Of The Most Commonly Used Targets

targetDesciptionMost Common Options
ACCEPT
  • iptables stops further processing.
  • The packet is handed over to the end application or the operating system for processing
N/A
DROP
  • iptables stops further processing.
  • The packet is blocked
N/A
LOG
  • The packet information is sent to the syslog daemon for logging
  • iptables continues processing with the next rule in the table
  • As you can't log and drop at the same time, it is common to have two similar rules in sequence. The first will log the packet, the second will drop it.
--log-prefix "string"
Tells iptables to prefix all log messages with a user defined string. Frequently used to tell why the logged packet was dropped
REJECT
  • Works like the DROP target, but will also return an error message to the host sending the packet that the packet was blocked
--reject-with qualifier
The qualifier tells what type of reject message is returned. Qualifiers include:
icmp-port-unreachable (default)
icmp-net-unreachable
icmp-host-unreachable
icmp-proto-unreachable
icmp-net-prohibited
icmp-host-prohibited
tcp-reset
echo-reply
DNAT
  • Used to do destination network address translation. ie. rewriting the destination IP address of the packet
--to-destination ipaddress
Tells iptables what the destination IP address should be
SNAT
  • Used to do source network address translation rewriting the source IP address of the packet
  • The source IP address is user defined
--to-source <address>[-<address>][:<port>-<port>]
Specifies the source IP address and ports to be used by SNAT.
MASQUERADE
  • Used to do Source Network Address Translation.
  • By default the source IP address is the same as that used by the firewall's interface
[--to-ports <port>[-<port>]]
Specifies the range of source ports to which the original source port can be mapped.

Important Iptables Command Switch Operations

Each line of an iptables script not only has a jump, but they also have a number of command line options that are used to append rules to chains that match your defined packet characteristics, such the source IP address and TCP port. There are also options that can be used to just clear a chain so you can start all over again. Tables 14.2 through 14.6 list the most common options.

Table 14-2 General Iptables Match Criteria

iptables command SwitchDesciption
-t <-table->If you don't specify a table, then the filter table is assumed. As discussed before, the possible built-in tables include: filter, nat, mangle
-j <target>Jump to the specified target chain when the packet matches the current rule.
-AAppend rule to end of a chain
-FFlush. Deletes all the rules in the selected table
-p <protocol-type>Match protocol. Types include, icmp, tcp, udp, and all
-s <ip-address>Match source IP address
-d <ip-address>Match destination IP address
-i <interface-name>Match "input" interface on which the packet enters.
-o <interface-name>Match "output" interface on which the packet exits

In this command switches example
iptables -A INPUT -s 0/0 -i eth0 -d 192.168.1.1  -p TCP -j ACCEPT
iptables is being configured to allow the firewall to accept TCP packets coming in on interface eth0 from any IP address destined for the firewall's IP address of 192.168.1.1. The 0/0 representation of an IP address means any.

Table 14-4 Common TCP and UDP Match Criteria

SwitchDesciption
-p tcp --sport <port>TCP source port. Can be a single value or a range in the format: start-port-number:end-port-number
-p tcp --dport <port>TCP destination port. Can be a single value or a range in the format: starting-port:ending-port
-p tcp --synUsed to identify a new TCP connection request. ! --syn means, not a new connection request
-p udp --sport <port>UDP source port. Can be a single value or a range in the format: starting-port:ending-port
-p udp --dport <port>UDP destination port. Can be a single value or a range in the format: starting-port:ending-port

In this example:
iptables -A FORWARD -s 0/0 -i eth0 -d 192.168.1.58 -o eth1 -p TCP \
         --sport 1024:65535 --dport 80 -j ACCEPT
iptables is being configured to allow the firewall to accept TCP packets for routing when they enter on interface eth0 from any IP address and are destined for an IP address of 192.168.1.58 that is reachable via interface eth1. The source port is in the range 1024 to 65535 and the destination port is port 80 (www/http).

Table 14-5 Common ICMP (Ping) Match Criteria

Matches used with ---icmp-typeDesciption
--icmp-type <type>The most commonly used types are echo-reply and echo-request

In this example:
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
iptables -A INPUT  -p icmp --icmp-type echo-reply   -j ACCEPT
iptables is being configured to allow the firewall to send ICMP echo-requests (pings) and in turn, accept the expected ICMP echo-replies.
Consider another example
iptables -A INPUT -p icmp --icmp-type echo-request \
         -m limit --limit 1/s -i eth0 -j ACCEPT
The limit feature in iptables specifies the maximum average number of matches to allow per second. You can specify time intervals in the format /second, /minute, /hour, or /day, or you can use abbreviations so that 3/second is the same as 3/s.
In this example, ICMP echo requests are restricted to no more than one per second. When tuned correctly, this feature allows you to filter unusually high volumes of traffic that characterize denial of service (DOS) attacks and Internet worms.
iptables -A INPUT -p tcp --syn -m limit --limit 5/s -i eth0 -j ACCEPT
You can expand on the limit feature of iptables to reduce your vulnerability to certain types of denial of service attack. Here a defense for SYN flood attacks was created by limiting the acceptance of TCP segments with the SYN bit set to no more than five per second.

Table 14-6 Common Extended Match Criteria

SwitchDesciption
-m multiport --sports <port, port>A variety of TCP/UDP source ports separated by commas. Unlike when -m isn't used, they do not have to be within a range.
-m multiport --dports <port, port>A variety of TCP/UDP destination ports separated by commas. Unlike when -m isn't used, they do not have to be within a range.
-m multiport --ports <port, port>A variety of TCP/UDP ports separated by commas. Source and destination ports are assumed to be the same and they do not have to be within a range.
-m --state <state>
The most frequently tested states are:
ESTABLISHED: The packet is part of a connection that has seen packets in both directions
NEW: The packet is the start of a new connection
RELATED: The packet is starting a new secondary connection. This is a common feature of such protocols such as an FTP data transfer, or an ICMP error.
INVALID: The packet couldn't be identified. Could be due to insufficient system resources, or ICMP errors that don't match an existing data flow.
This is an expansion on the previous example:
iptables -A FORWARD -s 0/0 -i eth0 -d 192.168.1.58 -o eth1 -p TCP \
         --sport 1024:65535 -m multiport --dports 80,443 -j ACCEPT
 
iptables -A FORWARD -d 0/0 -o eth0 -s 192.168.1.58 -i eth1 -p TCP \
         -m state --state ESTABLISHED -j ACCEPT
Here iptables is being configured to allow the firewall to accept TCP packets to be routed when they enter on interface eth0 from any IP address destined for IP address of 192.168.1.58 that is reachable via interface eth1. The source port is in the range 1024 to 65535 and the destination ports are port 80 (www/http) and 443 (https). The return packets from 192.168.1.58 are allowed to be accepted too. Instead of stating the source and destination ports, you can simply allow packets related to established connections using the -m state and --state ESTABLISHED options.

Using User Defined Chains

As you may remember, you can configure iptables to have user-defined chains. This feature is frequently used to help streamline the processing of packets. For example, instead of using a single, built-in chain for all protocols, you can use the chain to determine the protocol type for the packet and then hand off the actual final processing to a user-defined, protocol-specific chain in the filter table. In other words, you can replace a long chain with a stubby main chain pointing to multiple stubby chains, thereby shortening the total length of all chains the packet has to pass through. For example
iptables -A INPUT -i eth0  -d 206.229.110.2 -j fast-input-queue
iptables -A OUTPUT -o eth0 -s 206.229.110.2 -j fast-output-queue

iptables -A fast-input-queue  -p icmp -j icmp-queue-in
iptables -A fast-output-queue -p icmp -j icmp-queue-out

iptables -A icmp-queue-out -p icmp --icmp-type echo-request \
         -m state --state NEW -j ACCEPT

iptables -A icmp-queue-in -p icmp --icmp-type echo-reply -j ACCEPT
Here six queues help assist in improving processing speed. Table 14.7 summarizes the function of each.

Table 14.7 Custom Queues Example Listing

ChainDesciption
INPUTThe regular built-in INPUT chain in iptables
OUTPUTThe regular built-in OUTPUT chain in iptables
fast-input-queueInput chain dedicated to identifying specific protocols and shunting the packets to protocol specific chains.
fast-output-queueOutput chain dedicated to identifying specific protocols and shunting the packets to protocol specific chains.
icmp-queue-outOutput queue dedicated to ICMP
icmp-queue-inInput queue dedicated to ICMP

Saving Your iptables Scripts

The service iptables save command permanently saves the iptables configuration in the /etc/sysconfig/iptables file. When the system reboots, the iptables-restore program reads the configuration and makes it the active configuration.
The format of the /etc/sysconfig/iptables file is slightly different from that of the scripts shown in this chapter. The initialization of built-in chains is automatic and the string "iptables" is omitted from the rule statements.
Here is a sample /etc/sysconfig/iptables configuration that allows ICMP, IPSec (ESP and AH packets), already established connections, and inbound SSH.
[root@bigboy tmp]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.2.9 on Mon Nov 8 11:00:07 2004 
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [144:12748]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -m icmp --icmp-type 255 -j ACCEPT
-A RH-Firewall-1-INPUT -p esp -j ACCEPT
-A RH-Firewall-1-INPUT -p ah -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Mon Nov 8 11:00:07 2004
[root@bigboy tmp]#
It is never a good idea to edit this script directly because it is always overwritten by the save command and it doesn't save any comments at all, which can also make it extremely difficult to follow. For these reasons, you're better off writing and applying a customized script and then using the service iptables save command to make the changes permanent.

Fedora's iptables Rule Generator

Fedora comes with a program called lokkit that you can use to generate a very rudimentary firewall rule set. It prompts for the level of security and then gives you the option of doing simple customizations. It is a good place for beginners to start on a test system so that they can see a general rule structure.
Like the service iptables save command, lokkit saves the firewall rules in a new /etc/sysconfig/iptables file for use on the next reboot.
Once you have become familiar with the iptables syntax, it's best to write scripts that you can comment and then save it to /etc/sysconfig/iptables. It makes them much more manageable and readable.

Recovering From A Lost Script

Sometimes the script you created to generate iptables rules may get corrupted or lost, or you might inherit a new system from an administer and cannot find the original script used to protect it. In these situations, you can use the iptables-save and iptables-restore commands to assist you with the continued management of the server.
Unlike the service iptables save command, which actually saves a permanent copy of the firewall's active configuration in the /etc/sysconfig/iptables file, iptables-save displays the active configuration to the screen in /etc/sysconfig/iptables format. If you redirect the iptables-save screen output to a file with the > symbol, then you can edit the output and reload the updated rules when they meet your new criteria with the iptables-restore command.
This example exports the iptables-save output to a text file named firewall-config.
[root@bigboy tmp]# iptables-save > firewall-config
[root@bigboy tmp]# cat firewall-config
# Generated by iptables-save v1.2.9 on Mon Nov 8 11:00:07 2004
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [144:12748]
:RH-Firewall-1-INPUT - [0:0]
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp -m icmp --icmp-type 255 -j ACCEPT
-A RH-Firewall-1-INPUT -p esp -j ACCEPT
-A RH-Firewall-1-INPUT -p ah -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Mon Nov 8 11:00:07 2004
[root@bigboy tmp]#
After editing the firewall-config file with the commands you need, you can reload it into the active firewall rule set with the iptables-restore command.
[root@bigboy tmp]# iptables-restore < firewall-config
Finally, you should permanently save the active configuration so that it will be loaded automatically when the system reboots:
[root@bigboy tmp]# service iptables save
If desired, you can eventually convert this firewall-config file into a regular iptables script so that it becomes more easily recognizable and manageable.

Loading Kernel Modules Needed By iptables

The iptables application requires you to load certain kernel modules to activate some of its functions. Whenever any type of NAT is required, the iptable_nat module needs to be loaded. The ip_conntrack_ftp module needs to be added for FTP support and should always be loaded with the ip_conntrack module which tracks TCP connection states. As most scripts probably will keep track of connection states, the ip_conntrack module will be needed in any case. The ip_nat_ftp module also needs to be loaded for FTP servers behind a NAT firewall.
Unfortunately, the /etc/sysconfig/iptables file doesn't support the loading of modules, so you'll have to add the statements to your /etc/rc.local file which is run at the end of every reboot.
The script samples in this chapter include these statements only as a reminder to place them in the /etc/rc.local file
# File: /etc/rc.local

# Module to track the state of connections
modprobe ip_conntrack

# Load the iptables active FTP module, requires ip_conntrack
modprobe ip_conntrack_ftp
  
# Load iptables NAT module when required
modprobe iptable_nat
 
# Module required for active an FTP server using NAT
modprobe ip_nat_ftp

Sample iptables Scripts

This section provides some sample scripts you can use to get iptables working for you. Pay special attention to the logging example at the end.
The basic initialization script snippet should also be included in all your scripts to ensure the correct initialization of your chains should you decide to restart your script after startup. This chapter also includes other snippets that will help you get basic functionality. It should be a good guide to get you started.
Note: Once you feel more confident, you can use Appendix II "Codes, Scripts, and Configurations", to find detailed scripts. The appendix shows you how to allow your firewall to:
  • Be used as a Linux Web, mail and DNS server
  • Be the NAT router for your home network
  • Prevent various types of attacks using corrupted TCP, UDP and ICMP packets.
  • Provide outbound passive FTP access from the firewall
There are also simpler code snippets in the Appendix II "Codes, Scripts, and Configurations", for Inbound and outbound FTP connections to and from your firewall

Basic Operating System Defense

You can do several things before employing your firewall script to improve the resilience of your firewall to attack. For example, the Linux operating system has a number of built-in protection mechanisms that you should activate by modifying the system kernel parameters in the /proc filesystem via the /etc/sysctl.conf file. Using of /etc/sysctl.conf to modify kernel parameters is explained in more detail in , Appendix I "Miscellaneous Linux Topics".
Here is a sample configuration:
# File: /etc/sysctl.conf
 
#---------------------------------------------------------------
# Disable routing triangulation. Respond to queries out
# the same interface, not another. Helps to maintain state
# Also protects against IP spoofing
#---------------------------------------------------------------
 
net/ipv4/conf/all/rp_filter = 1
 
 
#---------------------------------------------------------------
# Enable logging of packets with malformed IP addresses
#---------------------------------------------------------------
 
net/ipv4/conf/all/log_martians = 1
 
 
#---------------------------------------------------------------
# Disable redirects
#---------------------------------------------------------------
 
net/ipv4/conf/all/send_redirects = 0
 
 
#---------------------------------------------------------------
# Disable source routed packets
#---------------------------------------------------------------
 
net/ipv4/conf/all/accept_source_route = 0
 
 
#---------------------------------------------------------------
# Disable acceptance of ICMP redirects
#---------------------------------------------------------------
 
net/ipv4/conf/all/accept_redirects = 0
 
 
#---------------------------------------------------------------
# Turn on protection from Denial of Service (DOS) attacks
#---------------------------------------------------------------
 
net/ipv4/tcp_syncookies = 1
 
 
#---------------------------------------------------------------
# Disable responding to ping broadcasts
#---------------------------------------------------------------
 
net/ipv4/icmp_echo_ignore_broadcasts = 1
 
#---------------------------------------------------------------
# Enable IP routing. Required if your firewall is protecting a
# network, NAT included
#---------------------------------------------------------------

net/ipv4/ip_forward = 1

Advanced iptables Initialization

You may also want to add some more advanced initialization steps to your script, including checks for Internet traffic from RFC1918 private addresses. The sample script snippet below outlines how to do this. More complex initializations would include checks for attacks using invalid TCP flags and directed broadcasts which are beyond the scope of this book.
The script also uses multiple user-defined chains to make the script shorter and faster as the chains can be repeatedly accessed. This removes the need to repeat the same statements over and over again.
You can take even more precautions to further protect your network. The complete firewall script in Appendix II "Codes, Scripts, and Configurations", outlines most of them.
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
#
# Define networks: NOTE!! You may want to put these "EXTERNAL"
# definitions at the top of your script.
#
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
 
EXTERNAL_INT="eth0"            # External Internet interface
EXTERNAL_IP="97.158.253.25"    # Internet Interface IP address
 
#---------------------------------------------------------------
# Initialize our user-defined chains
#---------------------------------------------------------------
 
iptables -N valid-src
iptables -N valid-dst
 
#---------------------------------------------------------------
# Verify valid source and destination addresses for all packets
#---------------------------------------------------------------
 
iptables -A INPUT   -i $EXTERNAL_INT -j valid-src
iptables -A FORWARD -i $EXTERNAL_INT -j valid-src
iptables -A OUTPUT  -o $EXTERNAL_INT -j valid-dst
iptables -A FORWARD -o $EXTERNAL_INT -j valid-dst
 
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
#
# Source and Destination Address Sanity Checks
#
# Drop packets from networks covered in RFC 1918 (private nets)
# Drop packets from external interface IP
#
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
 
iptables -A valid-src -s 10.0.0.0/8     -j DROP
iptables -A valid-src -s 172.16.0.0/12  -j DROP
iptables -A valid-src -s 192.168.0.0/16 -j DROP
iptables -A valid-src -s 224.0.0.0/4    -j DROP
iptables -A valid-src -s 240.0.0.0/5    -j DROP
iptables -A valid-src -s 127.0.0.0/8    -j DROP
iptables -A valid-src -s 0.0.0.0/8       -j DROP
iptables -A valid-src -d 255.255.255.255 -j DROP
iptables -A valid-src -s 169.254.0.0/16  -j DROP
iptables -A valid-src -s $EXTERNAL_IP    -j DROP
iptables -A valid-dst -d 224.0.0.0/4    -j DROP

Allowing DNS Access To Your Firewall

You'll almost certainly want your firewall to make DNS queries to the Internet. This is not because it is required for the basic functionality of the firewall, but because of Fedora Linux's yum RPM updater which will help to keep the server up to date with the latest security patches. The following statements will apply not only for firewalls acting as DNS clients but also for firewalls working in a caching or regular DNS server role.
#---------------------------------------------------------------
# Allow outbound DNS queries from the FW and the replies too
#
# - Interface eth0 is the internet interface
#
# Zone transfers use TCP and not UDP. Most home networks
# / websites using a single DNS server won't require TCP statements
#
#---------------------------------------------------------------
 
iptables -A OUTPUT -p udp -o eth0 --dport 53 --sport 1024:65535 \
         -j ACCEPT
 
iptables -A INPUT -p udp -i eth0 --sport 53 --dport 1024:65535 \
         -j ACCEPT

Allowing WWW And SSH Access To Your Firewall

This sample snippet is for a firewall that doubles as a web server that is managed remotely by its system administrator via secure shell (SSH) sessions. Inbound packets destined for ports 80 and 22 are allowed thereby making the first steps in establishing a connection. It isn't necessary to specify these ports for the return leg as outbound packets for all established connections are allowed. Connections initiated by persons logged into the Web server will be denied as outbound NEW connection packets aren't allowed.
#---------------------------------------------------------------
# Allow previously established connections
# - Interface eth0 is the internet interface
#---------------------------------------------------------------

iptables -A OUTPUT -o eth0 -m state --state ESTABLISHED,RELATED \
  -j ACCEPT

#---------------------------------------------------------------
# Allow port 80 (www) and 22 (SSH) connections to the firewall
#---------------------------------------------------------------

iptables -A INPUT -p tcp -i eth0 --dport 22 --sport 1024:65535 \
  -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -i eth0 --dport 80 --sport 1024:65535 \
  -m state --state NEW -j ACCEPT

Allowing Your Firewall To Access The Internet

This iptables script enables a user on the firewall to use a Web browser to surf the Internet. HTTP traffic uses TCP port 80, and HTTPS uses port 443.
Note: HTTPS (secure HTTP) is used for credit card transactions frequently, as well as by RedHat Linux servers running up2date. FTP and HTTP are frequently used with yum.
#---------------------------------------------------------------
# Allow port 80 (www) and 443 (https) connections from the firewall
#---------------------------------------------------------------

iptables -A OUTPUT -j ACCEPT -m state \
  --state NEW,ESTABLISHED,RELATED -o eth0 -p tcp \
  -m multiport --dports 80,443 --sport 1024:65535
 
#---------------------------------------------------------------
# Allow previously established connections
# - Interface eth0 is the internet interface
#---------------------------------------------------------------

iptables -A INPUT -j ACCEPT -m state --state ESTABLISHED,RELATED  \
-i eth0 -p tcp


If you want all TCP traffic originating from the firewall to be accepted, then remove the line:
-m multiport --dports 80,443 --sport 1024:65535

Allow Your Home Network To Access The Firewall

In this example, eth1 is directly connected to a home network using IP addresses from the 192.168.1.0 network. All traffic between this network and the firewall is simplistically assumed to be trusted and allowed.
Further rules will be needed for the interface connected to the Internet to allow only specific ports, types of connections and possibly even remote servers to have access to your firewall and home network.
#---------------------------------------------------------------
# Allow all bidirectional traffic from your firewall to the
# protected network
# - Interface eth1 is the private network interface
#---------------------------------------------------------------

iptables -A INPUT   -j ACCEPT -p all -s 192.168.1.0/24 -i eth1
iptables -A OUTPUT  -j ACCEPT -p all -d 192.168.1.0/24 -o eth1

Masquerading (Many to One NAT)

As explained in Chapter 2, "Introduction to Networking", masquerading is another name for what many call many to one NAT. In other words, traffic from all devices on one or more protected networks will appear as if it originated from a single IP address on the Internet side of the firewall.
Note: The masquerade IP address always defaults to the IP address of the firewall's main interface. The advantage of this is that you never have to specify the NAT IP address. This makes it much easier to configure iptables NAT with DHCP.
You can configure many to one NAT to an IP alias, using the POSTROUTING and not the MASQUERADE statement. An example of this can be seen in the static NAT section that follows.
Keep in mind that iptables requires the iptables_nat module to be loaded with the modprobe command for the masquerade feature to work. Masquerading also depends on the Linux operating system being configured to support routing between the internet and private network interfaces of the firewall. This is done by enabling IP forwarding or routing by giving the file /proc/sys/net/ipv4/ip_forward the value 1 as opposed to the default disabled value of 0.
Once masquerading has been achieved using the POSTROUTING chain of the nat table, you will have to configure iptables to allow packets to flow between the two interfaces. To do this, use the FORWARD chain of the filter table. More specifically, packets related to NEW and ESTABLISHED connections will be allowed outbound to the Internet, but only packets related to ESTABLISHED connections will be allowed inbound. This helps to protect the home network from anyone trying to initiate connections from the Internet:
#---------------------------------------------------------------
# Load the NAT module
#
# Note: It is best to use the /etc/rc.local example in this
#       chapter. This value will not be retained in the
#       /etc/sysconfig/iptables file. Included only as a reminder.
#---------------------------------------------------------------
 
modprobe iptable_nat

#---------------------------------------------------------------
# Enable routing by modifying the ip_forward /proc filesystem file
#
# Note: It is best to use the /etc/sysctl.conf example in this
#       chapter. This value will not be retained in the
#       /etc/sysconfig/iptables file. Included only as a reminder.
#---------------------------------------------------------------
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
#---------------------------------------------------------------
# Allow masquerading
# - Interface eth0 is the internet interface
# - Interface eth1 is the private network interface
#---------------------------------------------------------------
 
iptables -A POSTROUTING -t nat -o eth0 -s 192.168.1.0/24 -d 0/0 \
         -j MASQUERADE
 
#---------------------------------------------------------------
# Prior to masquerading, the packets are routed via the filter
# table's FORWARD chain.
# Allowed outbound: New, established and related connections
# Allowed inbound : Established and related connections
#---------------------------------------------------------------
 
iptables -A FORWARD -t filter -o eth0 -m state \
         --state NEW,ESTABLISHED,RELATED -j ACCEPT
 
iptables -A FORWARD -t filter -i eth0 -m state \
         --state ESTABLISHED,RELATED -j ACCEPT

Note: If you configure your firewall to do masquerading, then if should be the used as the default gateway for all your servers on the network.

Port Forwarding Type NAT (DHCP DSL)

In many cases home users may get a single DHCP public IP address from their ISPs. If a Linux firewall is also your interface to the Internet and you want to host a Web site on one of the NAT protected home servers, then you will have to use port forwarding. Here the combination of the firewall's single IP address, the remote server's IP address, and the source/destination port of the traffic can be used to uniquely identify a traffic flow. All traffic that matches a particular combination of these factors may then be forwarded to a single server on the private network.
Port forwarding is handled by the PREROUTING chain of the nat table. As in masquerading, the iptables_nat module has to be loaded and routing has to be enabled for port forwarding to work. Routing too must be allowed in iptables with the FORWARD chain, this includes all NEW inbound connections from the Internet matching the port forwarding port plus all future packets related to the ESTABLISHED connection in both directions:
#---------------------------------------------------------------
# Load the NAT module
#
# Note: It is best to use the /etc/rc.local example in this
#       chapter. This value will not be retained in the
#       /etc/sysconfig/iptables file. Included only as a reminder.
#---------------------------------------------------------------
 
modprobe iptable_nat

#---------------------------------------------------------------
# Get the IP address of the Internet interface eth0 (linux only)
#
# You'll have to use a different expression to get the IP address
# for other operating systems which have a different ifconfig output
# or enter the IP address manually in the PREROUTING statement
#
# This is best when your firewall gets its IP address using DHCP.
# The external IP address could just be hard coded ("typed in
# normally")
#---------------------------------------------------------------
 
external_int="eth0"
external_ip="`ifconfig $external_int | grep 'inet addr' | \
                       awk '{print $2}' | sed -e 's/.*://'`"
#---------------------------------------------------------------
# Enable routing by modifying the ip_forward /proc filesystem file
#
# Note: It is best to use the /etc/sysctl.conf example in this
#       chapter. This value will not be retained in the
#       /etc/sysconfig/iptables file. Included only as a reminder.
#---------------------------------------------------------------
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
#---------------------------------------------------------------
# Allow port forwarding for traffic destined to port 80 of the
# firewall's IP address to be forwarded to port 8080 on server
# 192.168.1.200
#
# - Interface eth0 is the internet interface
# - Interface eth1 is the private network interface
#---------------------------------------------------------------
 
iptables -t nat -A PREROUTING -p tcp -i eth0 -d $external_ip \
     --dport 80 --sport 1024:65535 -j DNAT --to 192.168.1.200:8080
 
#---------------------------------------------------------------
# After DNAT, the packets are routed via the filter table's
# FORWARD chain.
# Connections on port 80 to the target machine on the private
# network must be allowed.
#---------------------------------------------------------------
 
iptables -A FORWARD -p tcp -i eth0 -o eth1 -d 192.168.1.200 \
    --dport 8080 --sport 1024:65535 -m state --state NEW -j ACCEPT
 
iptables -A FORWARD -t filter -o eth0 -m state \
         --state NEW,ESTABLISHED,RELATED -j ACCEPT
 
iptables -A FORWARD -t filter -i eth0 -m state \
         --state ESTABLISHED,RELATED -j ACCEPT
 

Static NAT

In this example, all traffic to a particular public IP address, not just to a particular port, is translated to a single server on the protected subnet. Because the firewall has more than one IP address, I can't recommend MASQUERADE; it will force masquerading as the IP address of the primary interface and not as any of the alias IP addresses the firewall may have. Instead, use SNAT to specify the alias IP address to be used for connections initiated by all other servers in the protected network.
Note: Although the nat table NATs all traffic to the target servers (192.168.1.100 to 102), only connections on ports 80,443 and 22 are allowed through by the FORWARD chain. Also notice how you have to specify a separate -m multiport option whenever you need to match multiple non-sequential ports for both source and destination.
In this example the firewall:
  • Uses one to one NAT to make the server 192.168.1.100 on your home network appear on the Internet as IP addresses 97.158.253.26.
  • Creates a many to one NAT for the 192.168.1.0 home network in which all the servers appear on the Internet as IP address 97.158.253.29. This is different from masquerading
You will have to create alias IP addresses for each of these Internet IPs for one to one NAT to work.
#---------------------------------------------------------------
# Load the NAT module
#
# Note: It is best to use the /etc/rc.local example in this
#       chapter. This value will not be retained in the
#       /etc/sysconfig/iptables file. Included only as a reminder.
#---------------------------------------------------------------
 
modprobe iptable_nat
 
#---------------------------------------------------------------
# Enable routing by modifying the ip_forward /proc filesystem file
#
# Note: It is best to use the /etc/sysctl.conf example in this
#       chapter. This value will not be retained in the
#       /etc/sysconfig/iptables file. Included only as a reminder.
#---------------------------------------------------------------
 
echo 1 > /proc/sys/net/ipv4/ip_forward
 
#---------------------------------------------------------------
# NAT ALL traffic:
###########
# REMEMBER to create aliases for all the internet IP addresses below
###########
#
# TO:             FROM:           MAP TO SERVER:
# 97.158.253.26    Anywhere        192.168.1.100 (1:1 NAT - Inbound)
# Anywhere        192.168.1.100   97.158.253.26 (1:1 NAT - Outbound)
# Anywhere        192.168.1.0/24  97.158.253.29 (FW IP)
#
# SNAT is used to NAT all other outbound connections initiated
# from the protected network to appear to come from
# IP address 97.158.253.29
#
# POSTROUTING:
#   NATs source IP addresses. Frequently used to NAT connections from
#   your home network to the Internet
#
# PREROUTING:
#   NATs destination IP addresses. Frequently used to NAT
#   connections from the Internet to your home network
#
# - Interface eth0 is the internet interface
# - Interface eth1 is the private network interface
#---------------------------------------------------------------
 
# PREROUTING statements for 1:1 NAT
# (Connections originating from the Internet)

iptables -t nat -A PREROUTING -d 97.158.253.26 -i eth0 \
        -j DNAT --to-destination 192.168.1.100

# POSTROUTING statements for 1:1 NAT
# (Connections originating from the home network servers)

iptables -t nat -A POSTROUTING -s 192.168.1.100 -o eth0 \
         -j SNAT --to-source 97.158.253.26
 
# POSTROUTING statements for Many:1 NAT
# (Connections originating from the entire home network)

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 \
         -j SNAT -o eth0 --to-source 97.158.253.29

# Allow forwarding to each of the servers configured for 1:1 NAT
# (For connections originating from the Internet. Notice how you
# use the real IP addresses here)
 
iptables -A FORWARD -p tcp -i eth0 -o eth1 -d 192.168.1.100 \
    -m multiport --dports 80,443,22 \
    -m state --state NEW -j ACCEPT
 
 
# Allow forwarding for all New and Established SNAT connections
# originating on the home network AND already established
# DNAT connections
 
iptables -A FORWARD -t filter -o eth0 -m state \
         --state NEW,ESTABLISHED,RELATED -j ACCEPT
 
# Allow forwarding for all 1:1 NAT connections originating on
# the Internet that have already passed through the NEW forwarding
# statements above
 
iptables -A FORWARD -t filter -i eth0 -m state \
         --state ESTABLISHED,RELATED -j ACCEPT

Troubleshooting iptables

A number of tools are at your disposal for troubleshooting iptables firewall scripts. One of the best methods is to log all dropped packets to the /var/log/messages file.

Checking The Firewall Logs

You track packets passing through the iptables list of rules using the LOG target. You should be aware that the LOG target:
  • Logs all traffic that matches the iptables rule in which it is located.
  • Automatically writes an entry to the /var/log/messages file and then executes the next rule.
If you want to log only unwanted traffic, therefore, you have to add a matching rule with a DROP target immediately after the LOG rule. If you don't, you'll find yourself logging both desired and unwanted traffic with no way of discerning between the two, because by default iptables doesn't state why the packet was logged in its log message.
This example logs a summary of failed packets to the file /var/log/messages. You can use the contents of this file to determine which TCP/UDP ports you need to open to provide access to specific traffic that is currently stopped.
#---------------------------------------------------------------
# Log and drop all other packets to file /var/log/messages
# Without this we could be crawling around in the dark
#---------------------------------------------------------------
 
iptables -A OUTPUT -j LOG
iptables -A INPUT -j LOG
iptables -A FORWARD -j LOG
 
iptables -A OUTPUT -j DROP
iptables -A INPUT -j DROP
iptables -A FORWARD -j DROP

Here are some examples of the output of this file:
  • Firewall denies replies to DNS queries (UDP port 53) destined to server 192.168.1.102 on the home network.
Feb 23 20:33:50 bigboy kernel: IN=wlan0 OUT= MAC=00:06:25:09:69:80:00:a0:c5:e1:3e:88:08:00 SRC=192.42.93.30 DST=192.168.1.102 LEN=220 TOS=0x00 PREC=0x00 TTL=54 ID=30485 PROTO=UDP SPT=53 DPT=32820 LEN=200
  • Firewall denies Windows NetBIOS traffic (UDP port 138)
Feb 23 20:43:08 bigboy kernel: IN=wlan0 OUT= MAC=ff:ff:ff:ff:ff:ff:00:06:25:09:6a:b5:08:00 SRC=192.168.1.100 DST=192.168.1.255 LEN=241 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP SPT=138 DPT=138 LEN=221
  • Firewall denies Network Time Protocol (NTP UDP port 123)
Feb 23 20:58:48 bigboy kernel: IN= OUT=wlan0 SRC=192.168.1.102 DST=207.200.81.113 LEN=76 TOS=0x10 PREC=0x00 TTL=64 ID=0 DF PROTO=UDP SPT=123 DPT=123 LEN=56
The traffic in all these examples isn't destined for the firewall; Therefore, you should check your INPUT, OUTPUT, FORWARD, and NAT related statements. If the firewall's IP address is involved, then you should focus on the INPUT and OUTPUT statements
If nothing shows up in the logs, then follow the steps in Chapter 4, "Simple Network Troubleshooting", to determine whether the data is reaching your firewall at all and, if it is not, the location on your network that could be causing the problem.
As a general rule, you won't be able to access the public NAT IP addresses from servers on your home network. Basic NAT testing requires you to ask a friend to try to connect to your home network from the Internet.
You can then use the logging output in /var/log/messages to make sure that the translations are occurring correctly and iptables isn't dropping the packets after translation occurs.

iptables Won't Start

The iptables startup script expects to find the /etc/sysconfig/iptables before it starts. If none exists, then symptoms include the firewall status always being stopped and the /etc/init.d/iptables script running without the typical [OK] or [FAILED] messages.
If you have just installed iptables and have never applied a policy, then you will face this problem. Unfortunately, running the service iptables save command before restarting won't help either. You have to create this file.
[root@bigboy tmp]# service iptables start
[root@bigboy tmp]#

[root@bigboy tmp]# touch /etc/sysconfig/iptables
[root@bigboy tmp]# chmod 600 /etc/sysconfig/iptables

[root@bigboy tmp]# service iptables start
Applying iptables firewall rules: [  OK  ]
[root@bigboy tmp]#

Conclusion

A firewall is a critical part of any establishment that connects to an unprotected network such as the Internet, but a firewall is never sufficient. Web site security involves not just protection from corrupted packets or maliciously overwhelming volumes of traffic, but also involves daily data backups to help recovery from device failures, regular application patching, enforced password policies, restricted and monitored physical access to your servers, reliable power and cooling, secured cabling, redundant hardware, and, probably most importantly, well trained and motivated employees. Security should be viewed as anything that contributes to the desired risk-free functioning of your site, and it is well worth the money to invest in and learn from a book that specializes in the topic.