In my last post I had started a basic tutorial on iptables and implementing rules. Let me continue with examples and available options with iptables.
Creating user defined chains
Now by default as I had said in my last post Basic iptables tutorials in Linux I 3 chains are present in iptables which are NAT, filter and mangle but what if you want to create or add an extra CHAIN, so is it possible?
Well the answer is YES, you can create a new chain and use it as per your requirement where mostly this is done to reduce the complexity.
To create a new chain
# iptables -n INTRANET
This will create a new chain. You can verify the same
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain INTRANET (o references)
target prot opt source destination
Now as you can see above a new chain has been created now you need to divide the traffic or rules to INTRANET chain as per your requirement. Now for our case we can take any example to show you how it works
Create references for user defined chain
For our scenario we want all the rules for source 192.168.0.0/24 should be under INTRANET chain so remove the complexity as I don't want to struggle find my rules in the complete rules list as it can be very hectic with more than 100 rules.
# iptables -I INPUT 1 -s 192.168.0.0/24 -j INTRANET
So as per the above rule I am creating and inserting a new rule inside INPUT chain at no. 1 position as I want to give this rule max priority which says any rule which is created with source IP 192.168.0.0/24 will be visible under INTRANET chain.
# iptables -I INTRANET -p tcp --dport telnet -j DROP
So as per the above rule I am inserting a new rule inside INTRANET chain for source 192.168.0.0/24 (as we have already defined this IP source using our last rule for INTRANET chain) connection to telnet port 23 should be dropped.
Now lets see if our rule has been implemented properly using
# iptables -L INTRANET
Chain INTRANET (1 references)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:telnet
As per the above rule list any connection coming from 192.168.0.0/24 using port 23 will be dropped.
Rules can be varied for various sport, dport, source destination inside any user defined chain.
Some more example
Block port 22 from 192.168.0.30 for the local machine inside INTRANET chain.
# iptables -A INTRANET -s 192.168.0.30 -p tcp --dport 22 -j DROP
So as you see in the above rule I am appending a new rule inside INTRANET chain for source 192.168.0.30 and blocking communication from port no. 22
Rename user defined chain
# iptables -E old_chain_name new_chain_name
# iptables -E INTRANET EXTRANET
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
EXTRANET all -- 192.168.1.0/24 anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain EXTRANET (1 references)
target prot opt source destination
Delete user defined chain
# iptables -X INTRANET
Chain Policies
By this term I mean the default policies for all the chains which most of us miss. In case you re look at the chains below, consider the highlighted term.
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
INTRANET all -- 192.168.0.0/24 anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain INTRANET (1 references)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:telnet
Now as you see by default all the chains have default ACCEPT policy which can be dangerous for critical machines as apart from any rule which you have created all other connections are allowed.
Change default policies of chains
Now since we have created a new chain so we should change the default policy of INPUT chain as we only want those users to communicate with us whom we have allowed in our rules
# iptables -P INPUT DROP
TCP - uses 3-way handshake
- SYN
- SYN-ACK
- ACK
# iptables -L INPUT
Chain INPUT (policy DROP)
target prot opt source destination
INTRANET all -- 192.168.0.0/24 anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
So as you see now only those machines will be allowed to communicate with us which you will allow through rules in your machine.
TCP Matches - Connection Oriented
- TCP works on layer 4 also known as Connection oriented protocol.
- TCP packets contains information of sender as well as receiver.
- Eg: HTTP, FTP, telnet etc
The syntax used
-p tcp, --protocol tcp
--sport,--source-port
Example:
Block telnet connection from 192.168.1.0/24 for localhost using EXTRANET chain
# iptables -A EXTRANET -p tcp --dport telnet -j DROP
UDP Matches: - Connectionless
- UDP works on Layer 4 and is considered connection less protocol.
- UDP considered packets are considered much faster as compared to TCP because they are not as heavy as TCP as they do not contain much details on the packet.
- These are generally used for broadcasting.
- Eg: DNS, DHCP, syslog, NTP etc
The syntax used
-p udp, --protocol udp
--sport,--source-port - same source port as destination port
Internet Control Messaging Protocol (ICMP)
ICMP Types:
- echo-request - PING
- echo-reply - pong
- PING - local system sends via OUTPUT chain an echo-request(PING)
Remote system received echo-request in its INPUT chain => Remote system responds with an echo-reply(Pong)
The sysntax used
-p icmp, --protocol icmp
For more details on icmp ping protocol usage follow the below link
Iptables rules to block/allow icmp ping request in Linux
Match multiple ports with fewer rules
Now suppose you want to block multiple ports more than 5-6 for the same machine so imagine you will have to write 5-6 rules which will make the rules list look messy which you can fix by using a single rule for multiple ports.
Let me give you an example
Block connection from 192.168.0.100 from port 22,23,80,8080 to your machine in a single rule
# iptables -A INTRANET -s 192.168.0.30 -p tcp -m multiport --dport 22,23,80,8080 -j DROP
Here in above rule I am appending a new rule in INTRANET chain for source 192.168.0.30 defining that the rule is for multiple ports using -m switch for --dport 22,23,80,8080 to drop any connection from these ports.
Lets see if our rule was implemented properly
# iptables -L INTRANET
Chain INTRANET (1 references)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:telnet
DROP tcp -- 192.168.0.30 anywhere multiport dports ssh,telnet,http,webcache
Block the above ports for all machines from source 192.168.0.0/24
# iptables -A INTRANET -p tcp -m multiport --dport 22,23,80,8080 -j DROP
MAC address level filtering
Suppose you have blocked any source with IP 192.168.0.100 from connecting your machine, but what if it chages its ip to some other range. In that case your machine is not secure any more. So for these cases we use MAC address filtering where you block the MAC ID of the source machine from connection. This is a layer 2 blocking i.e. Data Link Layer
Block connection from machine with mac id 00:0C:29:BD:AC:81 from connecting your machine using port 23
# iptables -A INPUT -p tcp -m mac --mac-source 00:0C:29:BD:AC:81 --dport 23 -j DROP
# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere anywhere MAC 00:0C:29:BD:AC:81 tcp dpt:telnet
Log iptables traffic
Now how do you collect logs for all the rules in your iptables?
By default all the generated logs are stored in /var/log/messages and it not easy to look out for particularly iptables log inside /var/log/messages as it stores many other logs as well. So it is always a good idea to use a different file for iptables logs
NOTE: To enable logging by firewall we need to enable kernel level logging in the linux machine
Follow these steps for the same
# vi /etc/rsyslog.conf (In RHEL 5 or older /etc/syslog.conf) #### RULES ####
# Log all kernel messages to the console.
# Logging much else clutters up the screen.
kern.* /var/log/firewall.log
Uncomment the above line and make necessary change as shown with blue color
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none;kern.none /var/log/messages
Add an extra word "kern.none" as shown above
Restart the services
# service rsyslog restart
For RHEL 5 or older
# service syslog restart
Create a new rule to log all the taffic for telnet port
# iptables -A INPUT 1 -p tcp --dport telnet -j LOG
Now I will try to do telnet to my linux box(10.10.20.26) from source (10.10.20.30)
Let us check the log generated in firewall.log
# less /var/log/firewall.log
Sep 16 12:23:34 localhost kernel: IN=eth0 OUT= MAC=00:0c:29:bd:ac:80:ac:16:2d:00:00:87:08:00 SRC=10.10.20.30 DST=10.10.20.26 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=12317 DF PROTO=TCP SPT=58754 DPT=23 WINDOW=8192 RES=0x00 SYN URGP=0
Examples
Log all the traffic for ssh and telnet port on 10.10.20.26
# iptables -A INPUT -d 10.10.20.26 -p tcp -m multiport --dport 22,23 -j LOG
# less /var/log/firewall.log
Sep 16 12:32:22 localhost kernel: IN=eth0 OUT= MAC=00:0c:29:bd:ac:80:ac:16:2d:00:00:87:08:00 SRC=10.10.20.30 DST=10.10.20.26 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=4022 DF PROTO=TCP SPT=58707 DPT=22 WINDOW=256 RES=0x00 ACK URGP=0
Sep 16 12:32:22 localhost kernel: IN=eth0 OUT= MAC=00:0c:29:bd:ac:80:ac:16:2d:00:00:87:08:00 SRC=10.10.20.30 DST=10.10.20.26 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=4023 DF PROTO=TCP SPT=58707 DPT=22 WINDOW=246 RES=0x00 ACK URGP=0
So as you see a log has been reported for the attempt of connection inside firewall.log
But again what if you have created a log entry for multiple ports and sources so for those cases you can use --log-prefix to distribute the log traffic and makes easy visibility inside log.
LOG PREFIX
Examples:
# iptables -A INPUT -d 10.10.20.26 -p tcp -m multiport --dport 22,23 -j LOG --log-prefix "SSH ACCESS ATTEMPT: "
# less /var/log/messages
Sep 16 12:34:49 localhost kernel: SSH ACCESS ATTEMPT: IN=eth0 OUT= MAC=00:0c:29:bd:ac:80:ac:16:2d:00:00:87:08:00 SRC=10.10.20.30 DST=10.10.20.26 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=11101 DF PROTO=TCP SPT=58707 DPT=22 WINDOW=2429 RES=0x00 ACK URGP=0
Sep 16 12:34:49 localhost kernel: SSH ACCESS ATTEMPT: IN=eth0 OUT= MAC=00:0c:29:bd:ac:80:ac:16:2d:00:00:87:08:00 SRC=10.10.20.30 DST=10.10.20.26 LEN=92 TOS=0x00 PREC=0x00 TTL=64 ID=11102 DF PROTO=TCP SPT=58707 DPT=22 WINDOW=2429 RES=0x00 ACK PSH URGP=0
We can create a new chain which will contain all the log related rules
# iptables -N LOGGER
# iptables -I INPUT 1 -j LOGGER
So here we are creating a refrence where all the INPUT chain traffic will take the refrence of LOGGER chain for additional rules.
# iptables -I LOGGER -m multiport --dport 80,443,22,23 -j LOG
Here we are creating a rule for LOGGER chain to log all the traffic on ports 80,443,22 and 23
Please let me know your suggestion and feedback.
Related Articles
Iptables rules to allow/block ssh incoming/outgoing connection in Linux
Iptables rules to block/allow icmp ping request in Linux
iptables rules for Samba 4 in Red Hat Linux
Iptables for Samba server