Quick jump:
A hot item on the market nowadays is the "all-in-one" router+WAP+switch. This allows one to split a net connection across a number of computers. However, I've used these with less than successful results (router would inexplicibly drop connections at periodic intervals), and thusly now use a Linux box as my gateway to the internet. Not only can it do the router/WAP/switch combo, but (typically) for less cost and with far greater usability, as the gateway can also be used as a file server, print server, DNS server, NIS server, web server, mail server, SSH server, etc, etc. This web page is to help those who would like to set up a configuration that will allow for this, plus get a firewall up to keep it secure. The information here is pretty much general for any DHCP based ethernet connection to the internet (e.g. cable modems, most DSL services, etc.).
Here are a few things I'm assuming before we get started:
The computers on your LAN will need to be assigned IP addresses, so thats the first thing: pick a block of reserved addresses for private address space. As per the IANA standards set forth (see here, RFC1918, or RFC3330), this means you can use anything in the blocks:
as you can see from the masks, each one has a decreasing number of allotable addresses. So unless you have over 64,000 computers at home, go with the 192.168 block. I use a single class C network (network 3), and thusly use 192.168.3.x below.
Here's a summary of the necessary files you'll want to edit:
Note: you MUST *at least* edit the following:
dhcpd.conf:
option domain-name-servers 192.168.3.1, ns2.yourisp.com, ns3.yourisp.com;named.conf:
forwarders{ ns1.yourisp.com; ns2.yourisp.com; };192.168.3.db:
NS ns2.yourisp.com.ventura.c.db:
NS ns2.yourisp.com.put in values for any additional backup nameservers (e.g. those provided by your ISP) in the above lines!!! (Remember: redundancy good)
here are the rpms you'll probably need:
remember: Fedora is yum-friendly, so its a simple one liner to install the necessary goods:
$ yum install dhclient dhcp bind bind-utils bind-chroot
First we need to enable packet forwarding on the kernel level (more on what the hell this means later). Edit your /etc/sysctl.conf so it contains the following:
# Controls IP packet forwarding net.ipv4.ip_forward = 1Since most people have dynamic IP's, you'll probably also want:
# Enable dynamic-ip address hacking net.ipv4.ip_dynaddr = 1For other potentially worthwhile settings, you can check out my whole sysctl.conf file.
Now set the eth1 interface up, which we'll manually assign as 192.168.3.1 on our internal network. This is done by editing /etc/sysconfig/network-scripts/ifcfg-eth1 like so:
DEVICE=eth1 ONBOOT=yes BOOTPROTO=none # (put your correct value below) HWADDR=XX:XX:XX:XX:XX:XX IPADDR=192.168.3.1
With the latest versions of Fedora, SELinux is packaged/enabled. Although frustrating for some, I find it to be a great tool, albeit a bit difficult to learn initially. Anyway, if you want to go with the setup I'm describing, you'll need to add some security exceptions:
setsebool -P named_write_master_zones=1And you'll need to customize the security policy using the contents of mydhcp.te :
make -f /usr/share/selinux/devel/Makefile semodule -i mydhcp.ppThis is actually a solution that required some help from Dan Walsh, the guy-behind-the-guy at Fedora with regards to SELinux policies, see here for more.
Now for my favorite part. Before we bring up eth1, we'll want to protect our internal LAN. Further, we've only told the linux kernel to allowpacket forwarding. It won't actually do so until we provide it with some configuration parameters. Enter iptables, the userspace command to interface with the kernel firewalling subsystem. The concept is a simple one: filter packets as they arrive via eth0 and perform NAT (network address translation) for the LAN.
Most stock linux installs (nowadays) include a pre-configured and already running configuration of iptables. However, the Redhat/Fedora stock scripts aren't dynamic - i.e. we can't change certain parameters that may be set/unset during the DHCP lease negotiation process for our IP, or do so in a device-dependent manner. For example, I like to set my firewall to block reserved IP addresses (like those discussed above for internal networks), but sometimes my DHCP server is on a specific reserved address - which most likely is unknown before acquiring an IP or may likely change at some point. Also, I like to block my *own* IP address from trying to connect to my gateway - just as an extra precaution, but again is unknown information before the IP has actually been assigned. The one handy feature of dhclient (the DHCP client keeping track of your IP lease) is that it can run scripts at various parts of the lease negotiation process and provide all kinds of handy variables (like the assigned IP address or DHCP server). The punchline is, I ditch the the builtin iptables service in Fedora:
$ service network stop # (since we don't want our network up until we reconfigure iptables) $ chkconfig --levels 2345 iptables off $ service iptables stop
The next step depends on if your IP is static or dynamically assigned.
As per the manpage of dhclient, provide a /etc/dhclient-exit-hooks script. This script will be executed during all stages of the lease negotiation process (which is extra useful, since a firewall will be established *before* an IP is assigned), and even provide information as to which stage the process is at. (The script should be executable, of course.)
As you may see in /sbin/ifup, you can insert a /sbin/ifup-pre-local script. This is run for _every_ interface before its brought up, regardless of whether or not its dynamic -- but as we'll see below, this script will only get executed when the external interface (eth0 here) is being brought up.
Now to rundown the various parts of the script, since its the main part of setting up and understanding the gateway. The only big differences between the static/dynamic script are at the beginning:
This script is derived from the neato perl script levy, available here .
#!/bin/sh # firewall.rules - created by levy.pl on Mon Sep 10 11:35:04 2001 # this is a -skeleton- ruleset-- adapt as needed.
This set of shell code interprets the dhclient call and determines if anything needs to be done. If we're bringing up this interface from a fresh boot or restarting the interface (PREINIT), or we pass "FORCE" to this script via a manual call of the script, the traffic shaping script (more on this below ) needs to be called first. Any other reason to call this script just results in the script exiting, since the iptables rules are already established. The logger -t stuff logs the important information, which probably ends up in /var/log/messages.
# setup response based on dhclient input logger -t iptables reason: ${reason} # only run the script before bringing up an interface (or forced) if [ "x${reason}" = "xPREINIT" -o "x${1}" = "xFORCE" ]; then /usr/local/sbin/tc_shaper.sh restart else exit 0 fi logger -t iptables IP is ${new_ip_address} logger -t iptables DHCP gateway is ${new_dhcp_server_identifier}
Hint: Think of how this could be used to update a dynamically assigned dyndns hostname, for example using this handy script (be sure to set the script up with root only read/write/exec permissions)
If your IP is static, the script instead starts as:
which only sets up the firewall if we're configuring the external interface. This is handy, since it will only run through when IFext is being altered/reconfigured. Just be sure to set your static IP and DHCP server values above.
IFext="eth0" IFint="eth1" lannet="192.168.3.0/16" staticaddr="192.168.0.2/32" dhcpgate="192.168.0.1" if [ "${1}" != "ifcfg-${IFext}" ]; then exit 0 fi
This chunk of the script initializes some variables (they should be relatively self-explanatory), sets the default policies to DROP (i.e. drop all packets) and cleans out any existing rules.
# other definitions IFext="eth0" IFint="eth1" lannet="192.168.3.0/16" logger -t iptables Setting default policies # chain policies # drop everything and open stuff as necessary /sbin/iptables -P INPUT DROP /sbin/iptables -P FORWARD DROP /sbin/iptables -P OUTPUT DROP logger -t iptables Flushing tables /sbin/iptables -F /sbin/iptables -F INPUT /sbin/iptables -F OUTPUT /sbin/iptables -F FORWARD /sbin/iptables -F -t mangle /sbin/iptables -F -t nat /sbin/iptables -X /sbin/iptables -Z
Now to create (-N to create, -F to flush) and setup the DUMP table, which is where packets will be sent if they get dropped. First the packet is logged (up to a limit) based on the type of packet (icmp, tcp or udp) and a return packet is sent to indicate the error to the violating host. Finally, the packet is dropped.
logger -t iptables Creating user tables + rules # create DUMP table /sbin/iptables -N DUMP /sbin/iptables -F DUMP # limited logs /sbin/iptables -A DUMP -p icmp -m limit --limit 1/m --limit-burst 5 -j LOG --log-prefix "IPT ICMPDUMP: " /sbin/iptables -A DUMP -p tcp -m limit --limit 1/m --limit-burst 5 -j LOG --log-prefix "IPT TCPDUMP: " /sbin/iptables -A DUMP -p udp -m limit --limit 1/m --limit-burst 5 -j LOG --log-prefix "IPT UDPDUMP: " /sbin/iptables -A DUMP -p tcp -j REJECT --reject-with tcp-reset /sbin/iptables -A DUMP -p udp -j REJECT --reject-with--icmp-port-unreachable /sbin/iptables -A DUMP -j DROP
This second table will be used to make sure connections are allowed based on the state of the connection (thusly, a stateful table), and also shows off some of the power of iptables and the linux kernel firewalling code. We can use this table to allow connections *only* of if the connection has already been established (ESTABLISHED) or is associated with a connection that has already been started (RELATED) or is a new connection coming from an interface other than the external interface . Therefore, connections can only be initiated from *inside* the LAN. Otherwise, they're sent to the DUMP table we made above.
# Stateful table /sbin/iptables -N STATEFUL /sbin/iptables -F STATEFUL /sbin/iptables -I STATEFUL -m state --state ESTABLISHED,RELATED -j ACCEPT /sbin/iptables -A STATEFUL -m state --state NEW -i ! ${IFext} -j ACCEPT /sbin/iptables -A STATEFUL -j DUMP
Ok, now to protect our SSH port (note: this table can also be used for other ports/protocols, so feel free to modify it as you see fit), since it seems to be scanned rather heavily by most script kiddies these days. Rather than run denyhosts, I just use the following table:
Which stores IP addresses/ports (--rsource) in a table (named SSH) that checks to see if the connection attempt from that IP/port has occurred more than 3 times in the past minute. If not, we jump out of the table (RETURN) and allow the packet through. Otherwise, its dumped. We'll see how this is useful below.
# SSH protection table /sbin/iptables -N SSH /sbin/iptables -F SSH /sbin/iptables -A SSH -i ! ${IFext} -j RETURN /sbin/iptables -A SSH -m recent --name SSH --set --rsource /sbin/iptables -A SSH -m recent ! --rcheck --seconds 60 --hitcount 3 --name SSH --rsource -j RETURN /sbin/iptables -A SSH -j DUMP
Now to set up some tables to attempt avoiding SYN-floods and fragmented packets, both of which are Bad. The syn-flood table allows us to only accept 4 connections per second. If the packet falls under the limit, the -j RETURN flag allows it to "jump" back to the call to this chain. Otherwise, start dropping packets - don't even send them to the DUMP table.
# SYN protection table /sbin/iptables -N SYN-FLOOD /sbin/iptables -F SYN-FLOOD /sbin/iptables -A SYN-FLOOD -m limit --limit 1/s --limit-burst 4 -j RETURN /sbin/iptables -A SYN-FLOOD -j DROP /sbin/iptables -A INPUT -i ${IFext} -p tcp --syn -j SYN-FLOOD /sbin/iptables -A INPUT -p tcp -i ${IFext} ! --syn -m state --state NEW -j DROP # watch out for fragments /sbin/iptables -A INPUT -i ${IFext} -f -j LOG --log-prefix "IPT FRAGMENTS: " /sbin/iptables -A INPUT -i ${IFext} -f -j DROP
The next two lines either call the SYN-FLOOD table if the SYN flag is set (jumping back to this rule and continuing if its under the connection attempt limit), or dump the packet if its a new connection and the SYN flag *isn't* set (note the ! --syn -m state --state NEW statement). The final two lines drop any fragmented packets (-f), caused by missing parts of the TCP/IP header.
Now to start letting connections in. Anything coming in or out on the loopback interface is certainly OK. We also trust anything going out from the LAN.
logger -t iptables Setting input/output rules # allow loopback in /sbin/iptables -A INPUT -i lo -j ACCEPT # allow loopback and LAN out /sbin/iptables -A OUTPUT -o lo -j ACCEPT /sbin/iptables -A OUTPUT -p ALL -s ${lannet} -j ACCEPT
This is something you may not need, but be sure to check. I had to add this rule to prevent my ISP from being blocked by my firewall. Quite simply, the DHCP server was given a reserved address. In order to let it in, we have to explicitly declare it before blocking all the reserved addresses (see below). That way, this rule is matched first by the packet and the connection is allowed. Again, we only set this rule up if the DHCP server is defined by the script.
logger -t iptables Setting ISP specific rules # needs to be defined before reserved addresses, # since our ISP typically uses a reserved address for a DHCP server (sigh) /sbin/iptables -A INPUT -p tcp -i ${IFext} --sport bootps --dport bootpc -j ACCEPT /sbin/iptables -A INPUT -p udp -i ${IFext} --sport bootps --dport bootpc -j ACCEPT
This is pretty self explanatory. Just dump any connection purporting to be from a reserved IP address. You may want to remove this block of rules, but I try to be extra-cautious.
logger -t iptables Preventing reserved addresses # drop reserved addresses incoming as per IANA listing /sbin/iptables -A INPUT -i ${IFext} -s 0.0.0.0/8 -j DUMP <snip> /sbin/iptables -A INPUT -i ${IFext} -s 240.0.0.0/8 -j DUMP
Now to set up protocol specific rules. We'll allow certain ICMP connections which tend to be used for critical network functions. Filtering some of this stuff may screw up your connection. However, you may need to change these for your specific settings.
logger -t iptables Setting ICMP rules # allow certain inbound ICMP types /sbin/iptables -A INPUT -i ${IFext} -p icmp --icmp-type echo-reply -j ACCEPT /sbin/iptables -A INPUT -i ${IFext} -p icmp --icmp-type destination-unreachable -j ACCEPT /sbin/iptables -A INPUT -i ${IFext} -p icmp --icmp-type source-quench -j ACCEPT /sbin/iptables -A INPUT -i ${IFext} -p icmp --icmp-type echo-request -j ACCEPT /sbin/iptables -A INPUT -i ${IFext} -p icmp --icmp-type time-exceeded -j ACCEPT /sbin/iptables -A INPUT -i ${IFext} -p icmp --icmp-type parameter-problem -j ACCEPT
Next is TCP/UDP - I allow in SSH, authorization requests via INETD, and NTP calls (which I use to set my clock). Note how the SSH connection is checked first using the SSH table we created above. Whats also nice is that you can use this table with any of the other connections, so feel free to tweak this part of the table for your needs. Also, public port connections are allowed. You'll probably want to change these settings, depending on which services you want available from outside the LAN. Of course, one should always keep in mind the terms of service (TOS) set forth by your ISP (which most likely won't appreciate nor allow web servers, for example).
logger -t iptables Setting TCP/UDP rules # opened ports /sbin/iptables -A INPUT -p tcp -i ${IFext} --dport ssh -m state --state NEW -j SSH /sbin/iptables -A INPUT -p tcp -i ${IFext} --dport ssh -j ACCEPT /sbin/iptables -A INPUT -p tcp -i ${IFext} --dport auth -j ACCEPT /sbin/iptables -A INPUT -p udp -i ${IFext} --dport auth -j ACCEPT /sbin/iptables -A INPUT -p tcp -i ${IFext} --sport ntp --dport ntp -j ACCEPT /sbin/iptables -A INPUT -p udp -i ${IFext} --sport ntp --dport ntp -j ACCEPT # accept all other public ports /sbin/iptables -A INPUT -p tcp -i ${IFext} --dport 1024: -j ACCEPT /sbin/iptables -A INPUT -p udp -i ${IFext} --dport 33434: -j ACCEPT
This single line is the _real_ reason we called this script - to get NAT up and running. Anything coming from the LAN that is destined for the internet is masqueraded as coming from IFext before being sent out (i.e. postrouting). All in one line. Damnit, I love iptables.
logger -t iptables Turning on NAT # masquerade from internal network /sbin/iptables -t nat -A POSTROUTING -s ${lannet} -o ${IFext} -j MASQUERADE
I won't go over all this in detail, I'll just cover the salient points - whats being done here is to CLASSIFY our network traffic that comes from the LAN so that it can be shaped appropriately. What this means, in a nutshell, is an attempt to control network traffic in order to optimize or guarantee performance, low-latency, and/or bandwidth. For example, note that any packet from our VoIP address (192.168.3.3) is given a high priority, because I want my VoIP phone to be guaranteed a certain chunk of bandwidth. The script that handles these packets is what we called in the beginning, the tc_shaper.sh script, covered below . For more information on traffic shaping, and what some of these packets are that we're flagging, see the Linux Advanced Routing and Traffic Control page .
logger -t classifying packets for shaping voip="192.168.3.3" # classify packets # give "overhead" packets highest priority (VoIP, too) iptables -t mangle -A POSTROUTING -o ${IFext} --source ${voip} -j CLASSIFY --set-class 1:10 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --syn -m length --length 40:68 -j CLASSIFY --set-class 1:10 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --tcp-flags ALL SYN,ACK -m length --length 40:68 -j CLASSIFY --set-class 1:10 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --tcp-flags ALL ACK -m length --length 40:100 -j CLASSIFY --set-class 1:10 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --tcp-flags ALL RST -j CLASSIFY --set-class 1:10 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --tcp-flags ALL ACK,RST -j CLASSIFY --set-class 1:10 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --tcp-flags ALL ACK,FIN -j CLASSIFY --set-class 1:10 # interactive SSH traffic iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --sport ssh -m length --length 40:100 -j CLASSIFY --set-class 1:20 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --dport ssh -m length --length 40:100 -j CLASSIFY --set-class 1:20 # interactive mail or web traffic iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp -m multiport --sport http,imap,https,imaps -j CLASSIFY --set-class 1:30 # dns lookups iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --dport domain -j CLASSIFY --set-class 1:30 # ICMP, UDP iptables -t mangle -A POSTROUTING -o ${IFext} -p udp -j CLASSIFY --set-class 1:40 iptables -t mangle -A POSTROUTING -o ${IFext} -p icmp -m length --length 28:1500 -m limit --limit 2/s --limit-burst 5 -j CLASSIFY --set-class 1:40 # bulk traffic iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --sport ssh -m length --length 101: -j CLASSIFY --set-class 1:50 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --dport ssh -m length --length 101: -j CLASSIFY --set-class 1:50 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --sport 25 -j CLASSIFY --set-class 1:50 iptables -t mangle -A POSTROUTING -o ${IFext} -p tcp --dport 6667 -j CLASSIFY --set-class 1:50
Finally, anything else we haven't covered is pushed to the STATEFUL table we made above.
logger -t iptables Finish up # push everything else to state table /sbin/iptables -A INPUT -j STATEFUL /sbin/iptables -A FORWARD -j STATEFUL /sbin/iptables -A OUTPUT -j STATEFUL
Readers with a careful eye may notice some lines in the script that are commented out - I've left in a few useful bits and pieces that are handy for such things as port forwarding, feel free to use those as necessary.
As mentioned above, some of the packets that pass through our firewall script are "flagged" for shaping. In order to actually carry out the traffic shaping, we need to set up packet queues for different traffic, so we can tell linux we want certain traffic that utilizes small packets (like SSH) to get higher priority over other, bulkier traffic (like an FTP download, for example). So we need to use the linux command tc usingthis script. The script simply sets up several classes, which are basically of different rate limits that different packets can be sent through:
which creates a parent class and several child classes of different IDs (such as 1:40), with different minimum upload rates (i.e. tc will do its best to guarantee at least 18kbit/s for classid 1:50). The maximal rate should be (as a good rule of thumb) 90% of your maximal allowed upload rate (384kbit/s for my CM). For more details on what all the commands are in this script, see the TC shaper tutorial (which is what I based this script on).
$TC qdisc add dev $IFext root handle 1: htb default 60 $TC class add dev $IFext parent 1: classid 1:1 htb rate 356kbit $TC class add dev $IFext parent 1:1 classid 1:10 htb rate 128kbit ceil 356kbit prio 0 $TC class add dev $IFext parent 1:1 classid 1:20 htb rate 64kbit ceil 356kbit prio 1 $TC class add dev $IFext parent 1:1 classid 1:30 htb rate 32kbit ceil 356kbit prio 2 $TC class add dev $IFext parent 1:1 classid 1:40 htb rate 20kbit ceil 356kbit prio 3 $TC class add dev $IFext parent 1:1 classid 1:50 htb rate 18kbit ceil 356kbit prio 4 $TC class add dev $IFext parent 1:1 classid 1:60 htb rate 2kbit ceil 356kbit prio 5 $TC qdisc add dev $IFext parent 1:10 handle 10: sfq perturb 10 $TC qdisc add dev $IFext parent 1:20 handle 20: sfq perturb 10 $TC qdisc add dev $IFext parent 1:30 handle 30: sfq perturb 10 $TC qdisc add dev $IFext parent 1:40 handle 40: sfq perturb 10 $TC qdisc add dev $IFext parent 1:50 handle 50: sfq perturb 10 $TC qdisc add dev $IFext parent 1:60 handle 60: sfq perturb 10
The next step is to assign IP addresses to each machine on the LAN. A simple way to do this is just setup aliases in the /etc/hosts file of all the machines, but thats slightly time consuming depending on the size of the network. I prefer using a DHCP server, which comes with the dhclient package from ISC, but is packaged separately by RedHat/Fedora. Setting it up is a cinch - just download my dhcpd.conf file. Some more salient points of this file:
ddns-hostname = pick (option fqdn.hostname, option host-name, concat ("dhcp-", binary-to-ascii (10, 8, "-", leased-address))); option host-name = config-option server.ddns-hostname;
include "/etc/rndc.key"; zone ventura.c. { primary 127.0.0.1; key rndckey; } zone 3.168.192.in-addr.arpa. { primary 127.0.0.1; key rndckey; }
You'll probably want to change some of these settings (lease time, domain name, etc), but note this will affect the nameserver configuration as well.
One thing to keep in mind is dhcpd should only be visible from our LAN interface (eth1 in our examples so far). This is easy to do with the dhcpd command line switch "eth1". However, since we want dhcpd to start every time we boot the gateway, we'll need to add the flag to the Fedora start up script. This is specified in /etc/sysconfig/dhcpd, like so:
DHCPDARGS=eth1Finally, we need to tell Fedora to turn on dhcpd at boot time:
$ chkconfig --levels 345 dhcpd on
Ok, now lets configure the nameserver so it will work for all the LAN machines as well as store all the dynamic names (thanks to our DHCP server). First is the named.conf file, which I like to have set up in a chrooted jail under /var/named/chroot (this is conveniently included as part of the bind-chroot package). I'll just highlight the important parts:
These options set up the nameserver to listen on and allow queries from the LAN. They also set up some "backup" nameservers (the "forwarders", configure these to your settings) but do *not* allow zone transfers, which we don't need (and if we did, we could override this setting on a zone basis anyway).
options { directory "/var/named"; /* * If there is a firewall between you and nameservers you want * to talk to, you might need to uncomment the query-source * directive below. Previous versions of BIND always asked * questions using port 53, but BIND 8.1 uses an unprivileged * port by default. */ // query-source address * port 53; forwarders{ ns1.yourisp.com; ns2.yourisp.com; }; allow-transfer{ none; }; allow-query { 192.168.3/24; localhost; }; listen-on { 127.0.0.1; 192.168.3.1; }; };
This sets up both the forward and reverse master zones for our LAN, and specifies the files to use to configure those zones (detailed below). It also allows either the localhost or a key validated server to update those zones, which is important given our DHCPD setup. Note the keys match for both daemons (if your named is chrooted, make sure /etc/rndc.key and /var/named/chroot/etc/rndc.key match).
zone "ventura.c" IN { type master; file "slaves/ventura.c.db"; allow-update { localhost; key rndckey; }; }; zone "3.168.192.in-addr.arpa" in { type master; file "slaves/192.168.3.db"; allow-update { localhost; key rndckey; }; }; include "/etc/rndc.key";
logging { category dnssec { security_log; }; category update { security_log; }; category security { security_log; }; channel security_log { file "data/dns_security.log" versions 4 size 10m; print-time yes; print-category yes; print-severity yes; severity info; }; };This last bit sets up some additional logging from named, but you can remove this part if you'd like.
Here's the skeleton ventura.c.db and 192.168.3.db files, which only defines the nameserver (192.168.3.1 in our case) and any aliases you'd like for it (make sure these files are owned/grouped by named, and as of FC2 they should reside in the slaves subdirectory of /var/named). Be sure to change any of the lines labelled "ns2.yourisp.com" to match additional nameservers available for your clients. (If you'd like to understand the specifics of these files, check out the BIND ARM or get a copy of O'Reilly's DNS and BIND, both of which are great resources for everything you'll want to know about DNS and the configuration files provided here.)
Upon assigning IPs, the DHCP server will update these files periodically for you - you'll know its working if you see .jnl files, which correspond to zone journal files from any updates.
Now that we have the nameserver configured, its important to make sure the linux box knows to use it. The list of nameservers (in order of preference) is contained in /etc/resolv.conf. dhclient generates this file, and can be told to prepend nameservers and domain names for resolving by editing /etc/dhclient-eth0.conf as such:
# NOTE: the space at the end of "ventura.c " is significant!!! prepend domain-name "ventura.c "; prepend domain-name-servers 127.0.0.1;So our homemade nameserver is queried first, with our fake domain name appended to any host name query.
Now to enable the named service at boot time:
$ chkconfig --levels 345 named on
Ok, now to light this candle either type in the following or reboot the machine:
$ sysctl -p $ service network start $ service named start $ service dhcpd start(Its important to start named first, so its ready to receive name requests from the dhcp daemon) Check for errors in /var/log/messages. If none, setup the LAN machines to configure using DHCP. Reboot the LAN network interfaces, and watch the fun!!! To check things out, take a look at the logged packets in /var/log/messages under the subtext "IPT (TCP|UDP|ICMP)DUMP:", which might look something like this:
Jan 16 23:32:36 localhost kernel: IPT TCPDUMP: IN=eth0 OUT= MAC=xx SRC=xx DST=xx LEN=48 TOS=0x00 PREC=0x00 TTL=117 ID=39764 DF PROTO=TCP SPT=3415 DPT=80 WINDOW=64240 RES=0x00 SYN URGP=0Aha! someone (my isp server in this case, but I've blocked stuff out to protect the innocent) is attempting to make a TCP connection (note the SYN flag is set) on port 80 (DPT=80), which is typically where web servers reside. Since we didn't open up a hole on port 80 (nor do we allow new connections from eth0), this packet passes through the stateful table and ends up being dropped.
To further check the firewall, there are several options. The file /proc/net/ip_conntrack shows all current, active connections. To view all the tables rules, try the following script:
#!/bin/sh tables=$(cat /proc/net/ip_tables_names 2>/dev/null) for i in $tables ; do echo table $i iptables -t $i -L echo donewhich will show all the current rules and gory details. Further, Fedora has the logwatch analyzer running by default, so expect mailings in the root inbox detailing daily activities involving iptables (run as part of the kernel services script).
Now that the gateway is up and running, I suggest reading up and/or playing with some of the settings described (particularly iptables) to learn more about networking. Also, understanding and reading through the log files can be an interesting experience - you'll know what your ISP is doing and what potentially dangerous crackers are up to. Remember: the internet can be a harsh mistress.
I also had plans to add a wireless card to the mix, with the hopes of running the card in Master mode (as allowed by some of the prism54 chipsets, for example), thereby allowing me to run the router as a WAP as well. But after realizing how little information chipset manufacturers have provided for most major chipsets on the market for the purposes of driver development (and the wackiness involving PCI IDs - see here for a description), I gave up on using a wireless card under linux. Instead, I use an Asus WL-330g on an open port in the switch.
Q: named is starting, but its not producing journal files!
A: check the permissions on the /var/named/chroot/var/named/slaves directory. It should be owned and grouped by named, and so should the files (192.168.3.db and ventura.c.db) contained within it. If not, it might not be able to write the files. Alternatively, make sure the named server is being started before the dhcp server, so the dhcp server knows the name server is up and running and is using it. Or, if you're crazy enough to be using SELinux, you may want to check the labelling on the named files - just use restorecon to fix any file security contexts (e.g. restorecon /var/named/chroot/var/named/slaves/ventura.c.db).
Q: I have a dual boot machine behind the firewall, and its given two IP's - one for Windows, and a different one for linux! Whats up?
A: as per RFC 2131, the DHCP client can send a unique identifier to the DHCP server as a method of identifying itself. Microsoft clients pretty much *always* send the MAC address as the client-ID, although linux allows you to set this to whatever you want (as RFC 2131 puts no restriction on the client-ID, only that it should be "unique"). Therefore, just have your linux client also send its MAC address as the client-identifier, using /etc/dhclient-eth0.conf:
option dhcp-client-identifier <mac_address_goes_here>;