Overview
Any basic home router is a combination firewall/switch/wifi device. If you don't need wifi, you can get much finer-grained control of your home network by buying a low-power computer with 2 ethernet ports to use as your firewall, and then a cheap 4 or 8 port switch to do your switching. This gives you far better control and flexibility.
Here's how you configure Fedora 10 on a low-power firewall machine.
Install a minimum F10 install on your firewall computer.
Not covered here. As a general rule, use the DVD, use the i386 version (on the assumption that you are using smaller; low-power hardware).
Kernel Settings
Do NOT skip this step or your internal computers will not be able to reach the internet.
Fedora 10 by default does not allow packet forwarding, which is a fantastically sane default setting. However, this needs to be changed for your 2-ethernet-port computer to act as a firewall. Therefore, ensure /etc/sysctl.conf looks like this:
# Kernel sysctl configuration file for Red Hat Linux # # For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and # sysctl.conf(5) for more details. # Controls IP packet forwarding net.ipv4.ip_forward = 1 net.ipv4.icmp_echo_ignore_broadcasts = 1 # Controls source route verification net.ipv4.conf.default.rp_filter = 1 # Do not accept source routing net.ipv4.conf.default.accept_source_route = 0 # Controls the System Request debugging functionality of the kernel kernel.sysrq = 0 # Controls whether core dumps will append the PID to the core filename. # Useful for debugging multi-threaded applications. kernel.core_uses_pid = 1 # Controls the use of TCP syncookies net.ipv4.tcp_syncookies = 1
and reboot.
SELinux Settings
Make /etc/selinux/config look like this:
# This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of these two values: # targeted - Targeted processes are protected, # mls - Multi Level Security protection. SELINUXTYPE=targeted
and reboot.
Kill NetworkManager; Enable network
NetworkManager is wonderful for laptops and absolute crap for servers. Therefore, do this:
[root@router ~]# /etc/rc.d/init.d/NetworkManager stop [root@router ~]# chkconfig --list network # important to be ON! network 0:off 1:off 2:off 3:on 4:off 5:off 6:off [root@router ~]# chkconfig --list NetworkManager # important to be OFF! NetworkManager 0:off 1:off 2:off 3:off 4:off 5:off 6:off
Configure /etc/sysconfig/network:
NETWORKING=yes HOSTNAME=router.lan
NOTE: To get the MAC address of your ethernet cards,
use /sbin/ifconfig -a; even if the cards are not
running or configured, their mac addresses will show up. You
will want the mac addresses to ensure eth0 and eth1 are
bound to the correct jacks on your machine.
Configure /etc/sysconfig/network-scripts/ifcfg-eth1 (eth1 points to your cable modem and therefore acquires its IP address via DHCP):
DEVICE=eth1 HWADDR=00:08:9b:a2:ab:a0 # will be different for your machine BOOTPROTO=dhcp USERCTL=no ONBOOT=yes
Configure /etc/sysconfig/network-scripts/ifcfg-eth0 (eth0 points inside your network; ideally, it is connected to your switch, and everything else inside your network is connected to the switch too):
DEVICE=eth0 HWADDR=00:08:9b:a2:ab:a1 # will be different for your machine BOOTPROTO=none ONBOOT=yes NETMASK=255.255.255.0 IPADDR=192.168.1.1 NETWORK=192.168.1.0
DHCP and Caching DNS
For small home networks, dnsmasq accomplishes DHCP serving and DNS caching with aplomb.
[root@router ~]# yum install dnsmasq # could already be installed, harmless if so [root@router ~]# chkconfig --list dnsmasq # important to be ON! dnsmasq 0:off 1:off 2:off 3:on 4:off 5:off 6:off
Configure /etc/dnsmasq.conf
domain-needed bogus-priv local=/lan/ expand-hosts domain=lan interface=eth0 listen-address=127.0.0.1 #upstream nameservers # isn't there a way to get these via dhcp? server=68.87.71.226 # This will be different for your setup; consult your ISP server=68.87.73.242 # This will be different for your setup; consult your ISP server=68.87.64.146 # This will be different for your setup; consult your ISP dhcp-range=lan,192.168.1.100,192.168.1.149,12h dhcp-lease-max=100
iptables
First, disable Fedora 10's iptables:
[root@router ~]# chkconfig --list iptables # important to be OFF! iptables 0:off 1:off 2:off 3:off 4:off 5:off 6:off [root@router ~]# chkconfig --list ip6tables # important to be OFF! ip6tables 0:off 1:off 2:off 3:off 4:off 5:off 6:off
Now put in our own NATing firewall in /etc/rc.d/rc.local:
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
touch /var/lock/subsys/local
# /bin/loadkeys < /etc/rc.d/keydump # uncomment if you need unix keyboard mapping
# a subject covered elsewhere on this site
/etc/rc.d/iptables_nat_router.sh
And here is the firewall itself, courtesy the Linux Networking Cookbook, by Carla Schroder, O'Reilly, 2007:
#!/bin/sh # # iptables firewall script for sharing # broadband Internet, with no public services # # From Linux Networking Cookbook, by Carla Schroder, O'Reilly, 2007 # # NOTE! Forwarding will not work unless # /proc/sys/net/ipv4/ip_forward == '1', # perferably done in /etc/sysctl.conf # define variables ipt="/sbin/iptables" mod="/sbin/modprobe" LAN_IFACE="eth0" WAN_IFACE="eth1" #basic set of kernel modules # $mod ip_tables # on f10, compiled into kernel # $mod ip_conntrack # on f10, compiled into kernel # $mod iptable_filter # on f10, compiled into kernel $mod iptable_nat $mod iptable_mangle $mod ipt_LOG $mod ipt_limit # $mod ipt_state # on f10, compiled into kernel $mod ipt_MASQUERADE #add these for IRC and FTP $mod ip_nat_ftp $mod ip_nat_irc $mod ip_conntrack_ftp $mod ip_conntrack_irc # Flush all active rules and delete all custom chains $ipt -F $ipt -t nat -F $ipt -t mangle -F $ipt -X $ipt -t nat -X $ipt -t mangle -X #Set default policies $ipt -P INPUT DROP $ipt -P FORWARD DROP $ipt -P OUTPUT ACCEPT $ipt -t nat -P OUTPUT ACCEPT $ipt -t nat -P PREROUTING ACCEPT $ipt -t nat -P POSTROUTING ACCEPT $ipt -t mangle -P PREROUTING ACCEPT $ipt -t mangle -P POSTROUTING ACCEPT #this line is necessary for the loopback interface #and internal socket-based services to work correctly $ipt -A INPUT -i lo -j ACCEPT #Enable IP masquerading $ipt -t nat -A POSTROUTING -o $WAN_IFACE -j MASQUERADE #Enable unrestricted outgoing traffic, incoming #is restricted to locally-initiated sessions only $ipt -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT $ipt -A FORWARD -i $WAN_IFACE -o $LAN_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT $ipt -A FORWARD -i $LAN_IFACE -o $WAN_IFACE -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT # Allow ssh access from LAN, but not WAN $ipt -A INPUT -i $LAN_IFACE -p tcp -s 192.168.1.0/24 --dport 22 --syn -m state --state NEW -j ACCEPT # Allow DNS access from LAN $ipt -A INPUT -i $LAN_IFACE -p udp -s 192.168.1.0/24 --dport 53 -j ACCEPT $ipt -A INPUT -i $LAN_IFACE -p tcp -s 192.168.1.0/24 --dport 53 -j ACCEPT # Allow DHCP access from LAN $ipt -A INPUT -i $LAN_IFACE -p udp --dport 67 -j ACCEPT $ipt -A INPUT -i $LAN_IFACE -p udp --dport 68 -j ACCEPT # Accept important ICMP messages $ipt -A INPUT -p icmp --icmp-type echo-request -j ACCEPT $ipt -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT $ipt -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT #Reject connection attempts not initiated from inside the LAN $ipt -A INPUT -p tcp --syn -j DROP # XXX: what about dropping unwanted UDP?
Optional Config stuff
/etc/resolv.conf and /etc/hosts seem OK after eth1 gets configured via DHCP via your cable modem. But, if you want, you can add an entry to your firewall in /etc/hosts.
Install ntpd and start it if keeping accurrate time on your firewall is important to you
Logwatch
This section shows how to set up logwatch so that it e-mails the status of your firewall to your GMail account every day.
Ensure cron is installed, and python, and libgmail, and logwatch.
copy /usr/share/logwatch/default.conf/logwatch.conf to /etc/logwatch/conf/logwatch.conf
make these settings in /etc/logwatch/conf/logwatch.conf:
#MailTo = # notice how this is commented out #MailFrom = Logwatch # notice how this is commented out #Print = # notice how this is commented out too Save = /tmp/logwatch.txt # notice how this is not commented out
Everything else should already be in place for cron to launch logwatch daily.
Yum check
We also want daily status on yum updates e-mailed to us.
Create the file /etc/cron.daily/check_yum.sh:
#!/bin/sh yum check-update > /tmp/check_yum.txt 2>&1
e-mail logwatch and yum check to GMail
create /etc/cron.daily/zzz_email.py (named zzz* because jobs in cron.daily are executed in alphabetical order and we need e-mail to be sent AFTER logwatch and check yum check have run):
#!/usr/bin/python
import libgmail
f = open('/tmp/logwatch.txt', mode='rt')
logwatch = f.read()
f.close()
f = open('/tmp/check_yum.txt', mode='rt')
check_yum = f.read()
f.close()
message = logwatch + '\n\n' + check_yum
ga = libgmail.GmailAccount('my.gmail.username', 'mypassword')
ga.login()
gmsg = libgmail.GmailComposedMessage('my.gmail.username@gmail.com', 'router logwatch', message)
ga.sendMessage(gmsg)
Restart your firewall
...and start testing!