≡ Menu

iptables script

Iptables provides the option to log both IP and TCP headers in a log file. This is useful to:
=> Detect Attacks

=> Analyze IP / TCP Headers

=> Troubleshoot Problems

=> Intrusion Detection

=> Iptables Log Analysis

=> Use 3rd party application such as PSAD (a tool to detect port scans and other suspicious traffic)

=> Use as education tool to understand TCP / IP header formats etc.

How do I turn on Logging IP Packet Header Options?

Add the following command to your iptables script beo:

iptables -A INPUT -j LOG --log-ip-options
iptables -A INPUT -j DROP

How do I turn on Logging TCP Packet Header Options?

Add the following command to your iptables script:

iptables -A INPUT -j LOG --log-tcp-options
iptables -A INPUT -j DROP

You may need to add additional filtering criteria such as source and destination ports/IP-address and other connection tracking features. To see IP / TCP header use tail -f or grep command:
# tail -f /var/log/messages

Recommended readings:

Someone recently asked me a question:

How can I save time and script size by specifying a range of IP addresses or ports using iptables?

In old version of iptables IP address ranges are only valid in the nat table (see below for example). However newer version does support option that allows you to specify a range of IP addresses or ports for regular tables such as input.

Iptables set range of IP addresses

You need to use following options with match extensions (-m Ext).

iprange : This matches on a given arbitrary range of IPv4 addresses.

  • [!]--src-range ip-ip: Match source IP in the specified range.
  • [!]--dst-range ip-ip: Match destination IP in the specified range.

Syntax:

-m iprange --src-range IP-IP -j ACTION
-m iprange --dst-range IP-IP -j ACTION

For example, allow incoming request on a port 22 for source IP in the 192.168.1.100-192.168.1.200 range only. You need to add something as follows to your iptables script:

iptables -A INPUT -p tcp --destination-port 22 -m iprange --src-range 192.168.1.100-192.168.1.200 -j ACCEPT  

Port range

if --protocol tcp (-p tcp) is specified, you can specify source port range with following syntax:

  • --source-port port:port
  • --sport port:port

And destination port range specification with following option :

  • --destination-port port:port
  • --dport port:port

For example block lock all incoming ssh access at port 22, for source port range 513:65535:

iptables -A INPUT -p tcp -s 0/0 --sport 513:65535 -d 195.55.55.78 --dport 22 -m state --state NEW,ESTABLISHED -j DROP

On the other hand, just allow incoming ssh request with following port range:

iptables -A INPUT -p tcp -s 0/0 -d 195.55.55.78 --sport 513:65535 --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s 195.55.55.78 -d 0/0 --sport 22 --dport 513:65535 -m state --state ESTABLISHED -j ACCEPT

NAT table - range option

If you are using NAT table use options --to-source and --to-destination. For example IP address range:

iptables -t nat -A POSTROUTING -j SNAT --to-source 192.168.1.100-192.168.1.200

ALTERNATIVELY, try range of ports:

iptables -t nat -A POSTROUTING -j SNAT --to-source 192.168.1.100:2000-3000

Read man page of iptables for more information.

Iptables allow CIPE connection request

From my mail bag:

How do I accept CIPE connection requests coming from the outside?

CIPE stands for Crypto IP Encapsulation (see howto Establishing a CIPE Connection) . It is used to configure an IP tunneling device. For example, CIPE can be used to grant access from the outside world into a Virtual Private Network (VPN). All you need to find out CIPE number, once you got the number (device name) append following two IPTABLE rules (add rule to your iptables script) to script:

Iptables rules:

Add the following rules to your iptables script or configuration file:

iptables -A INPUT -p udp -i cipcb0 -j ACCEPT
iptables -A OUTPUT -p udp -o cipcb0 -j ACCEPT

CIPE use its own virtual device. It is use to transmit UDP packets so the above rule allows the cipcb0 interface to incoming request (no need to use eth0).

Replace cipcb0 with your actual device name.

References:

It is really a good idea to have one central logging host for security and performance reason. For example monitoring log files will help you to detect:
* Security risks (you can see failed login attempt, port scan etc) analysis
* Troubleshoot user login problem
* Save disk space
* If hard disk crashed on other hosts old logs will be available from centralized loghost

Linux (and other UNIX like systems) use sysklogd (or syslogd) utility. It is system logging facility. It support of both internet and unix domain sockets enables this utility package to support both local and remote logging from DSL/ADSL router or other hosts in your network.

Prepare syslogd to accept remote logging message

Open file /etc/init.d/sysklogd under Debian Linux to configure syslogd to accept remote message.
# vi /etc/init.d/sysklogd
Locate line SYSLOGD and edit it as follows:
SYSLOGD="-r"
The option (-r) will enable the facility to receive message from the network using an internet domain socket with the syslog service. The default is to not receive any messages from the network.

Save file and exit to shell prompt. Restart the sysklogd:
# /etc/init.d/sysklogd restart

A note about RHEL / CentOS / Fedora Linux User

If you are using Red Hat or Fedora Linux, edit file /etc/sysconfig/syslog:
# vi /etc/sysconfig/syslog
Make changes:
SYSLOGD="-r"
Restart syslogd:
# service syslog restart

Open UDP port 514

If you are, using iptables based firewall, insert following rule to your iptables script to accept connection from your network:

MYNET=192.168.1.0/24
SLSERVER=192.168.1.100
iptables -A INPUT -p udp -s $MYNET --sport 1024:65535 -d $SLSERVER --dport 514 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p udp -s $SLSERVER --sport 514 -d $MYNET --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT

192.168.1.100 is IP address of syslogd server. You need to restrict access to syslogd within your network (192.168.1.0/24) only.

Configure the Router to logging message to a centralized loghost

You can open web configuration interface and type IP address of centralized loghost (192.168.1.100) and port 514. Save configuration and reboot router.

Configure Linux or Unix host to logging message to a centralized loghost

You need to open syslog configuration file /etc/syslog.conf:
# vi /etc/syslog.conf
Setup syslogd to send all important message related to auth to loghost IP 192.168.1.100 (or use FQDN if configured)

*.*;auth,authpriv.none          @192.168.1.100

OR

*.*;auth,authpriv.none          @loghost.mydomain.com.

Restart sysklogd (Debian Linux):
# /etc/init.d/sysklogd restart
OR
Restart syslogd under Red Hat/Fedora / CentOS Linux
# service syslog restart
If required open outgoing UDP 514 port from other hosts:

# SYSLOG outgoing client request
iptables -A OUTPUT -p udp -s 192.168.1.100 --sport 1024:65535 -d 192.168.1.5 --dport 514 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp -s 192.168.1.5 --sport 514 -d 192.168.1.100 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT

Windows NT/2000/XP/Vista Desktop system

You can force your Windows NT/2000/XP desktop to log all messages to a centralized loghost. However, Windows do not have in build system to log message to remote Unix syslogd server. You can use NTsyslog program, which runs as a service under Windows NT based operating systems. It formats all System, Security, and Application events into a single line and sends them to a syslogd host.

Verify that message are logged in to your /var/log/messages# tail -f /var/log/messages
Output:
Feb 16 02:08:01 router  kernel: klogd started: BusyBox v1.00 (2005.09.22-19:11+0000)
Feb 16 02:08:01 router  kernel: Linux version 2.6.8.1 (root@localhost.localdomain) (gcc version 3.4.2) #1 Thu Sep 22 15:07:47 EDT 2005
Feb 16 02:08:01 router  kernel: Total Flash size: 2048K with 39 sectors
Feb 16 02:08:01 router  kernel: 96338L-2M-8M prom init
Feb 16 02:08:01 router  kernel: CPU revision is: 00029010
Feb 16 02:08:01 router  kernel: Determined physical RAM map:
Feb 16 02:08:01 router  kernel:  memory: 007a0000 @ 0000000
..........
...
......
Feb 16 02:08:01 router  kernel: AdslCoreHwReset: AdslOemDataAddr = 0xA07E504C
Feb 16 02:08:01 router  kernel: ip_tables: (C) 2000-2002 Netfilter core team
Feb 16 02:08:01 router  kernel: ip_conntrack version 2.1 (61 buckets, 0 max) - 368 bytes
Feb 16 02:08:06 router  pppd[224]: pppd 2.4.1 started by admin, uid 0
Feb 16 02:08:07 router  pppd[224]: PPP: Start to connect ...
Feb 16 02:08:10 router  dnsprobe[272]: dnsprobe started!

Linux Iptables allow or open IMAP server port

The Internet Message Access Protocol (commonly known as IMAP or IMAP4) is an application layer Internet protocol that allows a local client to access e-mail on a remote server. An IMAP protocol is used for e-mail retrieval. Virtually almost all modern e-mail clients and servers support IMAP.

E-mail messages are generally sent to an e-mail server that stores received messages in the recipient's e-mail mailbox. The user later retrieves these messages with either a web browser or an e-mail client that uses one of a number of e-mail retrieval protocols. While some clients and servers preferentially use vendor specific, typically proprietary protocols, most support the Internet standard protocols SMTP for sending e-mail and POP3 and IMAP4 for retrieving e-mail, allowing interoperability with other servers and clients.

Iptables allow or open IMAP server port

Following ports used by default
=> IMAP Port 143
=> SMTP Port 25

You can use iptables to open port 143. Just append following rules to your iptables script. It uses the TCP port 143. Following two iptable rules allows incoming IMAP request on port 143 for server IP address 202.54.1.20 (open port 143):
iptables -A INPUT -p tcp -s 0/0 --sport 1024:65535 -d 202.54.1.20 --dport 143 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -s 202.54.1.20 --sport 143 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT

In order to block port 143 simply use target REJECT instead of ACCEPT in above rules. If you are typing above rules at shell prompt save them:
# /etc/init.d/iptables save
OR
# iptables-save > /path/to/script.sh

A SYN flood is a form of denial-of-service attack in which an attacker sends a succession of SYN requests to a target's system. This is a well known type of attack and is generally not effective against modern networks. It works if a server allocates resources after receiving a SYN, but before it has received the ACK.

if Half-open connections bind resources on the server, it may be possible to take up all these resources by flooding the server with SYN messages. Syn flood is common attack and it can be block with following iptables rules:

iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j RETURN

All incoming connection are allowed till limit is reached:

  • --limit 1/s: Maximum average matching rate in seconds
  • --limit-burst 3: Maximum initial number of packets to match

Open our iptables script, add the rules as follows:

# Limit the number of incoming tcp connections
# Interface 0 incoming syn-flood protection
iptables -N syn_flood
iptables -A INPUT -p tcp --syn -j syn_flood
iptables -A syn_flood -m limit --limit 1/s --limit-burst 3 -j RETURN
iptables -A syn_flood -j DROP
#Limiting the incoming icmp ping request:
iptables -A INPUT -p icmp -m limit --limit  1/s --limit-burst 1 -j ACCEPT
iptables -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix PING-DROP:
iptables -A INPUT -p icmp -j DROP
iptables -A OUTPUT -p icmp -j ACCEPT

First rule will accept ping connections to 1 per second, with an initial burst of 1. If this level crossed it will log the packet with PING-DROP in /var/log/message file. Third rule will drop packet if it tries to cross this limit. Fourth and final rule will allow you to use the continue established ping request of existing connection.
Where,

  • ‐‐limit rate: Maximum average matching rate: specified as a number, with an optional ‘/second’, ‘/minute’, ‘/hour’, or ‘/day’ suffix; the default is 3/hour.
  • ‐‐limit‐burst number: Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number; the default is 5.

You need to adjust the –limit-rate and –limit-burst according to your network traffic and requirements.

Let us assume that you need to limit incoming connection to ssh server (port 22) no more than 10 connections in a 10 minute:

iptables -I INPUT -p tcp -s 0/0 -d $SERVER_IP --sport 513:65535 --dport 22 -m state --state NEW,ESTABLISHED -m recent --set -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 600 --hitcount 11 -j DROP
iptables -A OUTPUT -p tcp -s $SERVER_IP -d 0/0 --sport 22 --dport 513:65535 -m state --state ESTABLISHED -j ACCEPT

See also:

More information on recent patch can be found here