Setting Up Ubuntu as a
Firewall / Router / Nat
As described in the overview
I executed this task in three steps. This document describes the
second step in which eth0 was set to request an address using dhcp and
the Ubuntu system could replace the Linksys router.
eth0: Set to request an address via dhcp and connected directly to
cable modem.
eth1: Set as a static address (192.168.1.1) and connected to a switch
(replacing a Linksys router).
Note: The first two tasks of step one - installing a dhcp server
and enabling packet forwarding - are assumed to have been completed.
See those notes if you are starting here.
Set Interface Addresses
We need to have eth0 request an address using dhcp. The second network
interface, eth1, is the connection for my home network. It is set to
192.168.1.1 as was my previous Linksys router.
Set the file /etc/network/interfaces contents like so:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet dhcp
pre-up iptables-restore < /etc/iptables.rules
auto eth1
iface eth1 inet static
address 192.168.1.1
netmask 255.255.255.0
network 192.168.1.0
Configure DHCP Server
This has not changed from step one, so skip if already done.
Edit the file /etc/default/dhcp3-server and enter the line:
INTERFACES="eth1"
This should be the only line in the file unless you have more than two
network interfaces and need a dhcp server on another one.
Set DHCP Configuration
Edit the file /etc/dhcp3/dhcpd.conf and set your configuration.
Set the domain name as you want it to appear for the network. I have
the lease time set to 1 hour (3600 seconds). The default is 600.
The file has quite a few default entries.
Note: I have entered the
domain servers that appeared in the file "/etc/resolv.conf". Those were
populated when eth0 received an address from the cable modem. Your name
servers will be different. In step three we need to update these name
servers automatically.
My uncommented entries at this step are:
ddns-update-style none;
option domain-name "mydomain.com";
option domain-name-servers 68.185.34.67, 68.185.32.10, 68.116.46.115, 68.116.46.70;
default-lease-time 3600;
max-lease-time 7200;
option subnet-mask 255.255.255.0;
option broadcast-address 192.168.1.255;
option routers 192.168.1.1;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.100 192.168.1.150;
}
log-facility local7;
Set Up Firewall
The firewall rules will vary depending on your needs. Create some text
containing the initial iptables setting such as "iptable-rules-thisbox"
and load iptables with the command:
sudo sh iptables-rules-thisbox
This simply executes the rules as root. Then test the rules until they
meet your needs and you are satisfied with them. Now save the rules
like so:
iptables-save > /etc/iptables.rules
The rules I am using are listed below. Some of the addresses have
"x"
in the dotted notation. Those are addresses that are allowed to ssh
into my box. The "x" characters represent digits in addresses
meaningful to my requirements. You will need to tailor the firewall to
your specific needs.
EXT_IF=eth0 # Define your external interface here
INT_IF=eth1 # Define your internal interface here
INT_NET='192.168.1.0/24' # Define your internal network address here
IPTABLES="/sbin/iptables"
# Set up some default policies at this point to avoid any potential race
# condition between flushing the rules and setting up temporary blocks.
#
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
# Flush and delete existing chains
#
$IPTABLES -F
$IPTABLES -t nat -F
$IPTABLES -X
$IPTABLES -Z
# Temporary blocks while the chains are being set up
#
$IPTABLES -A INPUT -i ! lo -j DROP
$IPTABLES -A OUTPUT -o ! lo -j DROP
$IPTABLES -A FORWARD -j DROP
# Unblock loopback traffic right away.
#
$IPTABLES -A INPUT -i lo -j ACCEPT # Internal, no restrictions
# Log error, then drop
$IPTABLES -N ERRORDROP
$IPTABLES -A ERRORDROP -j LOG --log-level alert --log-prefix "netfilter:ERROR:generic: "
$IPTABLES -A ERRORDROP -j DROP
# Log, then drop
$IPTABLES -N LOGDROP
$IPTABLES -A LOGDROP -j LOG --log-prefix "netfilter:badpac: "
$IPTABLES -A LOGDROP -j DROP
# NoLog drop
$IPTABLES -N NOLOGDROP
$IPTABLES -A NOLOGDROP -j DROP
#SSH trusted host log connection...
$IPTABLES -N ssh-trusted-syn-log
$IPTABLES -A ssh-trusted-syn-log -p tcp --tcp-flags SYN SYN -j LOG --log-prefix "netfilter:SSH_TRUSTED: "
$IPTABLES -A ssh-trusted-syn-log -j ACCEPT
$IPTABLES -N ssh-in
$IPTABLES -A ssh-in -p tcp --tcp-flags SYN SYN -s 32.x.x.x/24 -j ssh-trusted-syn-log #Acme Outbound address
$IPTABLES -A ssh-in -p tcp --tcp-flags SYN SYN -s 24.x.x.x/32 -j ssh-trusted-syn-log #fred's box
$IPTABLES -A ssh-in -p tcp --tcp-flags SYN SYN -s 208.x.x.x/32 -j ssh-trusted-syn-log #joe's box
$IPTABLES -A ssh-in -p tcp --tcp-flags SYN SYN -s 75.x.x.x/32 -j ssh-trusted-syn-log #bob's box
$IPTABLES -A ssh-in -p tcp --tcp-flags SYN SYN -s 192.168.1.0/24 -j ssh-trusted-syn-log #TEMPORARY HACK while this box sits behind linksys
$IPTABLES -A ssh-in -j LOG --log-prefix "netfilter:SSH_ILLEGAL: "
$IPTABLES -A ssh-in -j DROP
#$IPTABLES -i eth0 -t nat -A PREROUTING -p tcp --dport ssh -j DNAT --to-destination 192.168.1.16 #all ssh is DNAT'd to p6;
# External-Input chain
$IPTABLES -N ext-in
$IPTABLES -A ext-in -m state --state ESTABLISHED,RELATED -j ACCEPT # Allow established and related connections/traffic
$IPTABLES -A ext-in -p tcp --dport ssh -j ssh-in #all "new" ssh external connections
$IPTABLES -A ext-in -p udp --dport 6798 -j ACCEPT # FWTOOL upd port
$IPTABLES -A ext-in -j LOGDROP
# Input chain
$IPTABLES -A INPUT -i $INT_IF -j ACCEPT # Internal, no restrictions
$IPTABLES -A INPUT -j ext-in # External interface(s)
$IPTABLES -A INPUT -j ERRORDROP # Shouldn't be here
# Output chain # The following takes care of an info leak problem if you configure any NAT port forwarding rules in the future.
$IPTABLES -A OUTPUT -o $EXT_IF -m state -p icmp --state INVALID -j DROP
# Forward chain
$IPTABLES -A FORWARD -i $INT_IF -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
#anything beyond here is NOT established, and is coming from an external interface
$IPTABLES -A FORWARD -p tcp --dport ssh -j ssh-in #all "new" ssh external connections
#FORWARD TABLE HAS A POLICY OF DROP, so if we didn't pick it up above, it's gone
#the question is HOW did it get here,
$IPTABLES -A FORWARD -j LOG --log-prefix "netfilter:ERROR:FORWARD: "
$IPTABLES -A FORWARD -j DROP
# NAT handling
$IPTABLES -t nat -A POSTROUTING -s $INT_NET -o $EXT_IF -j MASQUERADE
#open things up now that all is setup
$IPTABLES -D INPUT 1
$IPTABLES -D OUTPUT 1
$IPTABLES -D FORWARD 1