COIT13146 - System and Network Administration Making a Gateway As noted in the textbook, the use of dedicated network hardware devices for gateways and firewalls is preferred. However, for this course, we will be configuring our Ubuntu Server to act as both, simply because it is a readily accessible method for doing it and the fundamental configuration process is very similar. There are a number of commercial firewall appliances that are based on Linux. We will be adding an additional, virtual, network card to our server so that our server becomes the gateway between an internal and external network. All traffic will be directed 'through' our gateway which will provide NAT support for our internal network. We will also apply iptables rules that restrict what traffic is allowed to pass and, depending on the port address, where it should be redirected to. The gateway outlined below will act as a gateway, provide NAT, port forward into the internal network and act as a basic 'stateful packet filtering' firewall. Assumptions We have an up-to-date Ubuntu Server connected to the Internet. We have a solid understanding of NAT and what gateways and firewalls are and the purpose that they server. Building a Gateway Cloning We will use our existing 'Ubuntu Server' as a base for our new gateway. So we need to make a full clone named 'gateway', remembering to reset the MAC address and delete the /etc/udev/rules.d/70-persistent-net.rules to ensure that it is unique on our network. Rename the host (edit /etc/hostname and /etc/hosts files) to 'gateway' (this has been covered previously). Our VirtualBox machine listing should now look like the following: We should always make sure when new 'systems' are copied/restored that they are functioning correctly. We should make sure that our new gateway server allows us to access the Internet by doing a simple ping test to a server on the Internet (www.cqu.edu.au). Take note of the IP address that the gateway server has been assigned on the 'external' interface, so we can connect to it using PuTTY. Adding an Internal network card We will use the existing network card in our cloned gateway server (eth0) as the external connection since it should already be configured for that. We now need to add another virtual network card to allow our gateway server to connect to our internal network. With our gateway shutdown, we need to configure another adapter in VirtualBox. The screen dump above provides all of the settings. Ensure to select 'Adapter 2', enable the adapter, and attach it to the 'Internal Network' using the default name of 'intnet'. That's it; we didn't even have to get out of our chair to install a new network card in our server  Configuring the internal network Now we need to start our server, connect to the external interface using PuTTY and configure the new network card for a manually configured internal network. Once our server starts, start PuTTY, [Load] the saved session we had for our previous Ubuntu Server, change the name to 'gateway', update the IP address to match the new gateway server and [Save] the session - login to the gateway using PuTTY. We will be configuring the internal network to match our previously created userv1 and userv2 hosts. To see that our new card has been 'seen' by the operating system, type in the command: ubuntu@gateway:~$ ifconfig -a This should now list 3 devices; eth0 (external), eth1 (internal) and lo (loopback): eth0 Link encap:Ethernet HWaddr 08:00:27:cc:d6:0a inet addr:192.168.1.7 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fecc:d60a/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:72 errors:0 dropped:0 overruns:0 frame:0 TX packets:110 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:8172 (8.1 KB) TX bytes:18279 (18.2 KB) eth1 Link encap:Ethernet HWaddr 08:00:27:35:ad:0c BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:8 errors:0 dropped:0 overruns:0 frame:0 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:480 (480.0 B) TX bytes:480 (480.0 B) Notice that eth1 has no network configuration assigned. It is not mandatory to do, however many organisations will allocate the higher range of IP addresses to servers and lower ranges to clients (some do the reverse!). Following this convention we will use 192.168.12.254 as the internal address of our gateway. We need to configure eth1 of our gateway as follows (/etc/network/interfaces): # The loopback network interface auto lo iface lo inet loopback # The primary network interface auto eth0 iface eth0 inet dhcp # The internal network interface auto eth1 iface eth1 inet static address 192.168.12.254 network 192.168.12.0 netmask 255.255.255.0 broadcast 192.168.12.255 Restart the network: ubuntu@gateway:~$ sudo /etc/init.d/networking restart and check our network configuration: ubuntu@gateway:~$ ifconfig -a eth0 Link encap:Ethernet HWaddr 08:00:27:cc:d6:0a inet addr:192.168.1.7 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fecc:d60a/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:747 errors:0 dropped:0 overruns:0 frame:0 TX packets:696 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:66560 (66.5 KB) TX bytes:136010 (136.0 KB) eth1 Link encap:Ethernet HWaddr 08:00:27:35:ad:0c inet addr:192.168.12.254 Bcast:192.168.12.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe35:ad0c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:12 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:936 (936.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:16 errors:0 dropped:0 overruns:0 frame:0 TX packets:16 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:960 (960.0 B) TX bytes:960 (960.0 B) eth1 is now configured for the internal network (192.168.12.0/24). As mentioned previously it is always a good idea to test our configuration as we go - if we leave it until later, it makes it much harder to diagnose problems if they occur. If we start our userv1 server from last week, we should be able to ping our gateways' internal interface at 192.168.12.254 and we should be able to ping userv1 (192.168.12.1) from the gateway. We need to ensure this is working before proceeding further. At this stage userv1 should not be able to access the Internet through our gateway as additional configuration is required. Viewing the routing table on the gateway may help our understanding of the configuration: ubuntu@gateway:~$ route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default 192.168.1.1 0.0.0.0 UG 100 0 0 eth0 192.168.1.0 * 255.255.255.0 U 0 0 0 eth0 192.168.12.0 * 255.255.255.0 U 0 0 0 eth1 The routing table shows that the gateway is connected externally (eth0) to a network, 192.168.1.0/24, with a gateway device 192.168.1.1 - in this case, the gateway device 192.168.1.1 is an ADSL router connected to the Internet. This might be a good time for us to create a network diagram and include it in our documentation - label servers, IP addresses and interfaces (e.g. eth0, eth1). If we are not able to ping between userv1 and the gateway, we need to review the network configuration on both our servers. Raise any issues on the course forum, providing details of the /etc/network/interfaces file, 'ifconfig -a' output and the routing table. Enable port forwarding Our gateway server is configured with connections to an internal and external network. We now need to configure a path between the internal and external networks, 'through' the gateway. The first thing we need to do is configure the kernel on our gateway to allow IP packets to be forwarded between the two interfaces. To do this we need to change a kernel parameter which can be found in the /etc/sysctl.conf file. A 'man sysctl.conf' and 'man sysctl' will provide some useful details. Edit the /etc/sysctl.conf file and uncomment the line (it should be line 28): #net.ipv4.ip_forward=1 by removing the '#' and saving the file. We can change the kernel parameters at runtime, but it is a useful test to ensure that they 'stick' after a reboot, so we will elect to simply reboot our server for the change to take effect. Log back in to the gateway using PuTTY once it has rebooted. To check that the setting has 'stuck' we can run the following command: ubuntu@gateway:~$ cat /proc/sys/net/ipv4/ip_forward We should see that the value is indeed now set to 1. If we ping the external IP address of our gateway, from our internal userv1 server, we should be able to 'see' the external interface of our gateway. In this example, the external IP address of the gateway is 192.168.1.12: ubuntu@userv1:~$ ping 192.168.1.12 PING 192.168.1.12 (192.168.1.12) 56(84) bytes of data. 64 bytes from 192.168.1.12: icmp_req=1 ttl=64 time=0.872 ms 64 bytes from 192.168.1.12: icmp_req=2 ttl=64 time=0.812 ms ... The gateway knows how to send a response back to userv1 as the network 192.168.12.0/24 is configured in its routing table. However, if we ping a host on the external network for example our host computer (i.e. the Windows host running Virtual Box - run ipconfig at the Windows command line to find its IP address), it fails. Why? The answer is that our gateway does not know to forward packets on to other networks. NAT NAT was covered in a prerequisite course and included in a previous weeks reading, so we won't cover how it works in detail here. We will however look at how it is enabled on our gateway. Our gateway needs to route packets using NAT for outgoing traffic so that our internal servers can access external resources. Using iptables we can add a rule that enables NAT for outgoing traffic (external output eth0 with IP address 192.168.1.12 - external IP addresses will differ): ubuntu@gateway:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j SNAT \ --to 192.168.1.12 If our external IP address changes frequently (we connect to different networks) we can use the MASQUERADE target which 'reads' the IP address of the external interface (eth0) dynamically - don't use both of these rules, if in doubt, use the one below: ubuntu@gateway:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE There are some security issues with using the MASQUERADE target, but we will overlook them for convenience, as some of us will likely move between networks - this would not be the case for a 'real' gateway server. Our gateway now knows to forward packets out via eth0 and enable NAT on the outgoing traffic. We should now be able to connect through our gateway to external networks, with our gateway providing NAT. From userv1, try pinging www.cqu.edu.au - it should succeed. Try a traceroute to www.cqu.edu.au - what are the first two entries? Securing the gateway - firewall and port forwarding A quick note about iptables rules - iptables rules do not persist on reboot. So if we reboot our server our iptables rules will not be in place when the server restarts. This can be a good thing if we make a mistake with our iptables rules - reboot and we can start again. We can write and implement scripts to save our iptables rules when the server shuts down, and restore those saved rules when the server starts up. However, for now, we will elect to simply write scripts that can be manually run when we want to set our iptables rules. Since iptables can be very confusing when first encountered, we will work on a basic configuration which we will extend on. We already have our NAT rule above, so let's create a basic script that flushes all previous rules and sets our NAT rule. We should create our own script based on the one below. Read through the man page for iptables to get a better understanding of what each of the built-in tables and chains are for.   #!/bin/sh # # FILE: buildfw # # PURPOSE: Clear and set NAT, port forward and firewall iptables rules. # # AUTHOR: Myles Greber # DATE: 23-02-2012 # VERSION: 0.1 # # USAGE: buildfw # # MODIFIED: # # NOTES: This script assumes the following configuration: # gateway: # eth0 - 192.168.1.12 - external (dhcp) # eth1 - 192.168.12.254 - internal (static) # internal server: # eth0 - 192.168.12.1 (static) # ################################################################################ # Flush all iptables rules from the packet matching tables. iptables -t filter -F iptables -t nat -F iptables -t mangle -F iptables -t raw -F # Reset the built-in chain policies to accept all traffic. iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT # Enable NAT on outgoing interface. iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE #iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 192.168.1.12 Now we should test our script. ubuntu@gateway:~$ sudo ./buildfw Ensure that it allows internal servers (userv1) to access remote sites as we had working previously. We should know that any good firewall configuration will first disable all access to everything and then add back in only those rules that are required. The first rules should be to drop all packets coming into and forwarded by the gateway. # Drop all packets coming in to and forwarded by the gateway. iptables -P INPUT DROP iptables -P FORWARD DROP Add these rules above where we enabled NAT and test it. ubuntu@gateway:~$ sudo ./buildfw Hopefully we have discovered that this was not the best thing to do when logged in via SSH - the SSH port is now effectively disabled. This is a good lesson to learn. Imagine that we were doing this on a server (virtual or real) hosted on a remote site. How would we access our server now? "...could someone reboot the server for me please?" We have the luxury of having our virtual server located locally, so login to the VirtualBox interface and comment out the last two lines that we just added to our script and re-run it. This will flush those last two rules and should allow us to use PuTTY (SSH) again. It is always a good idea to test these types of things locally first. Even if working perfectly locally, we must think the process through carefully when working remotely. It is easy to use the "shutdown -r +60" command if we are working on something that my lock us out of our server. As long as we don't include a script in our start-up process that locks us out, the server will reboot in 60 minutes and reset itself. We can cancel the shutdown at any time with the "-c" option. Planning is crucial for a System Administrator. Now let's temporarily enable SSH on the external interface so that we can continue to develop the script using PuTTY. Add the following to the end of the script. Uncomment the 'Drop all packets' rules from above. # Allow SSH connections to the external IP address of the gateway for testing. iptables -A INPUT -i eth0 -d 192.168.1.12 -p tcp --dport 22 -j ACCEPT Test it using PuTTY. Hopefully our SSH connection continues to function as it should. We must remember to comment out this line once we are happy we have the script working correctly. If we attempt to do anything directed at, or through the gateway from the internal network everything is blocked. So userv1 can't even ping the gateway anymore. Similarly if we try to ping our gateway from our host computer (Windows) we don't receive a response. The only thing available is our SSH connection. So now our gateway is a 'brick' wall, not a firewall  We don't want to restrict traffic outbound from our internal network, so we need to allow all outbound traffic from the internal interface (eth1) to be forwarded through the gateway. We also need to allow matching responses to that outbound traffic, to return to the requesting internal hosts through the gateway. # Allow all connections through the firewall that originate from within. iptables -A FORWARD -i eth1 -p ALL -j ACCEPT # Allow returned responses to internal host requests. iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT For NAT to work, it requires the traffic to pass through the gateway. So this rule should be placed directly above the enable NAT rule. Run and test the new rules by pinging www.cqu.edu.au from userv1 - this traffic should now pass through the gateway and receive a response. userv1 should not be able to ping the gateway internally and your host computer should not be able to ping the gateway externally. All of the above rules are discussed in the textbook and we can find more details in the man page for iptables. We should understand what each rule is doing. If there is any doubt, raise a question on the course forum. To ensure we have worked through the above correctly, the full script is provided below: #!/bin/sh # # FILE: buildfw # # PURPOSE: Clear and set NAT, port forward and firewall iptables rules. # # AUTHOR: Myles Greber # DATE: 23-02-2012 # VERSION: 0.1 # # USAGE: buildfw # # MODIFIED: # # NOTES: This script assumes the following configuration: # gateway: # eth0 - 192.168.1.12 - external (dhcp) # eth1 - 192.168.12.254 - internal (static) # internal server: # eth0 - 192.168.12.1 (static) # ################################################################################ # Flush all iptables rules from the packet matching tables. iptables -t filter -F iptables -t nat -F iptables -t mangle -F iptables -t raw -F # Reset the built-in chain policies to accept all traffic. iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT # Drop all packets coming into and forwarded by the gateway. iptables -P INPUT DROP iptables -P FORWARD DROP # Allow all connections through the firewall that originate from within. iptables -A FORWARD -i eth1 -p ALL -j ACCEPT # Allow incoming responses to internal host requests. iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # Enable NAT on outgoing interface. iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE #iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 192.168.1.12 # Allow SSH connections to the external IP address of the gateway for testing. iptables -A INPUT -i eth0 -d 192.168.1.12 -p tcp --dport 22 -j ACCEPT Hopefully the above has given us enough experience to be able to make some basic additions to our firewall rules. Remember we can always reboot the machine to clear all iptables rules. iptables rules can be difficult to grasp - use the course forum for help. In reality there are many preconfigured firewall rule sets available, however it is of value to have a good understanding of iptables rules.