This is another tutorial from the series of tutorials that describe building Linux Layer 3 switch on x86 hardware. In a previous tutorial we connected our switch to the Internet via routed port. To connect LAN users to the Internet we have to configure NAT and firewall on the switch.
The article shows firewall and NAT configuration. It does not explain how IP packets filtering or IP masquerade are working, for more information visit these websites:
http://en.wikipedia.org/wiki/Firewall_%28computing%29
http://en.wikipedia.org/wiki/Network_address_translation
1. Check if service itables is running
[root@swouter-x86 ~]# etc/init.d/iptables status
iptables: Firewall is not running.
The warning message "iptables: Firewall is not running" tells us that iptables service is not running. We have to start iptables service with the command:
[root@swouter-x86 ~]#/etc/init.d/iptables start
iptables: Applying firewall rules: [ OK ]
Check iptables status again:
[root@swouter-x86 ~]#/etc/init.d/iptables status
Table: nat
Chain PREROUTING (policy ACCEPT)
num target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Table: filter
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
5 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
From the output above we can see that two tables are loaded - NAT and Filter table. We need them both - table NAT for masquerading and table filter for firewalling.
If table is not presented you can easily load it to Linux kernel with the command.
[root@swouter-x86 ~]#modprobe iptable_filter
[root@swouter-x86 ~]#modprobe iptable_nat
The third table is Mangle table and it is not shown in the output. This table is used for Quality Of Service (QOS) and we are not going to use it. If it is loaded and you are not going to use QoS unload it with the command:
[root@swouter-x86 ~]#rmmod iptable_mangle
2. Flush rules from table filter and nat
This is the list of options that we are going to use. Both options are correct, use one of them for writing rules.
--flush
= -F
--table
= -t
--append
= -A
--out-interface
= -o
--in-interface
= -i
--jump
= -j
a) Flush Filter table
If you do not specify the concrete table, your changes will always be done on Filter table as it is considered as the default iptable. For example:
[root@swouter-x86 ~]#iptables --flush
meaning the same as:
[root@swouter-x86 ~]#iptables -t filter --flush
but we can use a shorter version as well:
[root@swouter-x86 ~]#iptables -F
b) Flush NAT table
[root@swouter-x86 ~]#iptables -t nat -F
3. NAT configuration
Outside NAT interface is ppp0.
Inside NAT interface is vlan1.
[root@swouter-x86 ~]#iptables --table nat -A POSTROUTING -o ppp0 --jump MASQUERADE
Save iptables:
[root@swouter-x86 ~]#/etc/init.d/iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables: [ OK ]
Check NAT table configuration in detail:
[root@swouter-x86 ~]#iptables -t nat -L -v
Chain PREROUTING (policy ACCEPT 2 packets, 528 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- any ppp0 anywhere anywhere
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Traffic coming from any inside interface with any source IP address via outside interface ppp0 will be translated. So far any translation has been done because - pkts counter is null.
4. Firewal configuration
a) Check default filter policy
[root@swouter-x86 ~]#iptables -L -v
Chain INPUT (policy ACCEPT 140 packets, 14016 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 1726 packets, 145K bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 113 packets, 9052 bytes)
pkts bytes target prot opt in out source destination
Default configured policy is set to ACCEPT for all the chains. Assuming NAT is working you should be able to ping from LAN to the Internet. If you do that, counter pkts for POSTROUTING policy in NAT table should increased every time translation of source IP address in packet is performed.
b) Change default filter policy
As long as default filter policy is set to ACCEPT all traffic is allowed, if it is not explicitly denied. The Cisco IOS ACLs work in different way - what is not explicitly allowed, it is denied by default. It is more secure way and we are going to implement it. This method allows us to explicitly define each type of traffic that should be allowed to pass through firewall.
First we need to change default filter policy to DENY for all the chains in firewall iptable.
Note: During playing with iptable filter it is recommended to be connected to box via serial port. It is very like to be disconnected if something goes wrong.
[root@swouter-x86 ~]#iptables -P INPUT DROP
[root@swouter-x86 ~]#iptables -P OUTPUT DROP
[root@swouter-x86 ~]#iptables -P FORWARD DROP
You might notice that now you cannot ping local interface of the router from the host in LAN, because INPUT chain is set as DROP. Yo cannot ping from the router to the Internet because OUTPUT chain is set to DROP. Also ping from the host in LAN to the Internet is not working due to DROP policy for FORWARD chain.
c) Allow ssh connection from LAN to router and vice versa
We need to allow traffic from subnet 172.18.0.0/16 with destination TCP port 22 (ssh) coming to interface vlan1
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -s 172.18.0.0/16 -p tcp --dport ssh -j ACCEPT
Packet coming from LAN to VLAN1 interface, with destination TCP port 22 (ssh) can reach vlan1 interface but ssh connection cannot be established. The default DROP policy in OUPUT chain blocks traffic originating from local interface of router. We need to add command to allow connection with source TCP port 22 from vlan1 interface to the hosts on LAN
[root@swouter-x86 ~]#iptables -A OUTPUT -p tcp --sport 22 -o vlan1 -d 172.18.0.0/16 -j ACCEPT
Now hosts on LAN can connect to the router using ssh. If we want to allow establish ssh connection from vlan1 of router to the hosts on LAN we have to to add following two commands.
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -s 172.18.0.0/16 -p tcp --sport ssh -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -d 172.18.0.0/16 -p tcp --dport ssh -j ACCEPT
d) Allow ping from hosts on LAN to default gateway and vice versa
Ping is kind of ICMP message. Following rule allows icmp request coming from the subnet 172.18.0.0/16 to VLAN1 interface.
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -s 172.18.0.0/16 -p icmp -j ACCEPT
We need also add the rule which allows to send ICMP echo message from VLAN1 interface to the host on 172.18.0.0/16 subnet.
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -d 172.18.0.0/16 -p icmp -j ACCEPT
e) Allow ping, DNS, http/https, ssh originating on router's ppp0 interface to reach the Internet
ICMP
[root@swouter-x86 ~]#iptables -A OUTPUT -o ppp0 -p icmp -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i ppp0 -p icmp -m state --state ESTABLISHED -j ACCEPT
We can ping hosts on the Internet but they cannot ping ppp0 ineterface. Only established icmp connection are allowed on ppp0 interface.
ICMP localhost
[root@swouter-x86 /]#iptables -A OUTPUT -o lo -p icmp -j ACCEPT
[root@swouter-x86 /]#iptables -A INPUT -i lo -p icmp -j ACCEPT
This rule allows to ping loopback interface itself and ping local interfaces from router.
DNS client
[root@swouter-x86 ~]#iptables -A OUTPUT -o ppp0 -p udp --dport 53 -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i ppp0 -p udp --sport 53 -m state --state ESTABLISHED -j ACCEPT
The rule allows to send DNS query to provider's DNS server.
Local DNS server - access from LAN
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -p udp --dport 53 -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -p udp --sport 53 -j ACCEPT
The rule allows DNS request coming from LAN to reach local DNS server running on router.
DNS server - router's own queries of local DNS server
[root@swouter-x86 /]#iptables -A INPUT -i lo -p udp -j ACCEPT
[root@swouter-x86 /]#iptables -A OUTPUT -o lo -p udp -j ACCEPT
DNS queries originating on router to local DNS server will be allowed.
HTTP/HTTPS
We need to allow http traffic originating on router to receive CentOS updates.
[root@swouter-x86 ~]#iptables -A OUTPUT -o ppp0 -p tcp --dport 80 -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUT PUT -o ppp0 -p tcp --dport 443 -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i ppp0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i ppp0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
SSH to the Internet
[root@swouter-x86 ~]#iptables -A OUTPUT -o ppp0 -p tcp --dport 22 -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i ppp0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
f) NTP client and server rules
Allow NTP client running on router to be sychronized with public NTP server.
[root@swouter-x86 ~]#iptables -A OUTPUT -o ppp0 -p udp --dport 123 -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i ppp0 -p udp --sport 123 -j ACCEPT
Allow NTP server to provide service to the hosts on LAN.
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -p udp --dport 123 -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -p udp --sport 123 -j ACCEPT
g) Allow DHCP requests from LAN to to reach DHCP server and vice versa
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -p udp --dport 67 -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -p udp --dport 68 -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -p udp --sport 67 -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -p udp --sport 68 -j ACCEPT
h) Allow host on LAN to access Samba server
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -p tcp -m multiport --dport 137,138,139,445 -j ACCEPT
[root@swouter-x86 ~]#iptables -A INPUT -i vlan1 -p udp -m multiport --dport 137,138,139,445 -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -p tcp -m multiport --sport 137,138,139,445 -j ACCEPT
[root@swouter-x86 ~]#iptables -A OUTPUT -o vlan1 -p udp -m multiport --sport 137,138,139,445 -j ACCEPT
i) Allow only established sessions coming from the Internet to be forwarded to LAN
[root@swouter-x86 ~]#/sbin/iptables -A FORWARD -i ppp0 -o vlan1 -m state --state RELATED,ESTABLISHED -j ACCEPT
j) Allow any traffic originating on LAN to be forwarded to the Internet
[root@swouter-x86 ~]#/sbin/iptables -A FORWARD -i vlan1 -o ppp0 -j ACCEPT
k) Check filter table
[root@swouter-x86 ~]#iptables -L -v
Chain INPUT (policy DROP 56 packets, 7156 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT icmp -- vlan1 any 172.18.0.0/16 anywhere
145 12353 ACCEPT tcp -- vlan1 any 172.18.0.0/16 anywhere tcp dpt:ssh
0 0 ACCEPT tcp -- vlan1 any 172.18.0.0/16 anywhere tcp spt:ssh
0 0 ACCEPT icmp -- ppp0 any anywhere anywhere state ESTABLISHED
401 54442 ACCEPT udp -- ppp0 any anywhere anywhere udp spt:domain state ESTABLISHED
8 948 ACCEPT tcp -- ppp0 any anywhere anywhere tcp spt:http state ESTABLISHED
7 1837 ACCEPT tcp -- ppp0 any anywhere anywhere tcp spt:https state ESTABLISHED
0 0 ACCEPT tcp -- ppp0 any anywhere anywhere tcp spt:ssh state ESTABLISHED
20 1552 ACCEPT icmp -- lo any anywhere anywhere
11 836 ACCEPT udp -- vlan1 any anywhere anywhere udp dpt:ntp
37 2812 ACCEPT udp -- ppp0 any anywhere anywhere udp spt:ntp
304 19672 ACCEPT udp -- vlan1 any anywhere anywhere udp dpt:domain
20 1559 ACCEPT udp -- lo any anywhere anywhere
4 200 ACCEPT tcp -- lo any anywhere anywhere
1 328 ACCEPT udp -- vlan1 any anywhere anywhere udp dpt:bootps
0 0 ACCEPT udp -- vlan1 any anywhere anywhere udp dpt:bootpc
65 11009 ACCEPT tcp -- vlan1 any anywhere anywhere multiport dports netbios-ns,netbios-dgm,netbios-ssn,microsoft-ds
139 13812 ACCEPT udp -- vlan1 any anywhere anywhere multiport dports netbios-ns,netbios-dgm,netbios-ssn,microsoft-ds
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1800 1232K ACCEPT all -- ppp0 vlan1 anywhere anywhere state RELATED,ESTABLISHED
2481 305K ACCEPT all -- vlan1 ppp0 anywhere anywhere
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
90 10749 ACCEPT tcp -- any vlan1 anywhere 172.18.0.0/16 tcp spt:ssh
0 0 ACCEPT icmp -- any vlan1 anywhere 172.18.0.0/16
0 0 ACCEPT tcp -- any vlan1 anywhere 172.18.0.0/16 tcp dpt:ssh
16 1488 ACCEPT icmp -- any ppp0 anywhere anywhere
401 27246 ACCEPT udp -- any ppp0 anywhere anywhere udp dpt:domain
10 718 ACCEPT tcp -- any ppp0 anywhere anywhere tcp dpt:http
8 933 ACCEPT tcp -- any ppp0 anywhere anywhere tcp dpt:https
0 0 ACCEPT tcp -- any ppp0 anywhere anywhere tcp dpt:ssh
20 1552 ACCEPT icmp -- any lo anywhere anywhere
11 836 ACCEPT udp -- any vlan1 anywhere anywhere udp spt:ntp
37 2812 ACCEPT udp -- any ppp0 anywhere anywhere udp dpt:ntp
304 39665 ACCEPT udp -- any vlan1 anywhere anywhere udp spt:domain
20 1559 ACCEPT udp -- any lo anywhere anywhere
4 200 ACCEPT tcp -- any lo anywhere anywhere
0 0 ACCEPT udp -- any vlan1 anywhere anywhere udp spt:bootpc
0 0 ACCEPT udp -- any vlan1 anywhere anywhere udp spt:bootps
74 9590 ACCEPT tcp -- any vlan1 anywhere anywhere multiport sports netbios-ns,netbios-dgm,netbios-ssn,microsoft-ds
0 0 ACCEPT udp -- any vlan1 anywhere anywhere multiport sports netbios-ns,netbios-dgm,netbios-ssn,microsoft-ds
5. Allow forwarding between interfaces
[root@swouter-x86]#sysctl -w net.ipv4.ip_forward=1
[root@swouter-x86]#sysctl -w net.ipv6.conf.all.forwarding=1
To enable forwarding at boot time, you edit /etc/sysctl.conf and change/add the following line.
net.ipv4.ip_forward = 1
net.ipv6.conf.default.forwarding=1
6. Save and restart iptables
[root@swouter-x86 ~]#/etc/init.d/iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables: [ OK ]
[root@swouter-x86 ~]# /etc/init.d/iptables restart
iptables: Flushing firewall rules: [ OK ]
iptables: Setting chains to policy ACCEPT: filter nat [ OK ]
iptables: Unloading modules: [ OK ]
iptables: Applying firewall rules: [ OK ]
Make iptables to be started after boot.
[root@swouter-x86 ~]# chkconfig iptables on
END.
Here is the list of articles I intensively used during writing.
http://www.yolinux.com/TUTORIALS/LinuxTutorialIptablesNetworkGateway.html
http://www.bctes.com/nat-linux-iptables.html
http://billauer.co.il/ipmasq-html.html
https://help.ubuntu.com/community/IptablesHowTo
http://www.gentoo.org/doc/en/home-router-howto.xml
http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers