How to configure a combined firewall & internet router using Linux

OK, here we are beginning to take the first step towards the actual productive use of the system. This of course depends very much on you particular requirements. In my case the requirements were these:

The last three are not strictly necessary for an internet gateway, but they make maintenance so much easier. In theory every additional component introduces a security risk, so in critical environments they should be avoided. A single SSH service might be a suitable replacement. It's up to you.

How to configure PPP

First of all, you need kernel support for PPP. The next important thing is to start the ppp daemon, which unsurprisingly is called pppd. In fact, to make handling the ppp interface easier, it is advisable to create a shell script that can start, stop or restart the daemon. I created /etc/rc.d/rc.pppd for this purpose:

#!/bin/sh
# Start/stop/restart the ppp daemon.
#
# Martin Rogge, 04/07/2002
#

pppd_start() {
  if [ -x /usr/sbin/pppd ]; then
    echo "Starting PPP daemon:  /usr/sbin/pppd"
    /usr/sbin/pppd call isp >/dev/tty6 2>/dev/tty6
  else
    echo "WARNING:  /usr/sbin/pppd not found."
  fi
}

pppd_stop() {
  echo "Sending pppd the SIGTERM signal..."
  killall -15 pppd 2> /dev/null
}

pppd_restart() {
  echo "Sending pppd the SIGHUP signal..."
  killall -1 pppd 2> /dev/null
}

case "$1" in
'start')
  pppd_start
  ;;
'stop')
  pppd_stop
  ;;
'restart')
  pppd_restart
  ;;
*)
  echo "usage: rc.pppd start|stop|restart"
esac

As you can see from the pppd_start function, the daemon is called with the parameters "call isp". This basically instructs pppd to open the file /etc/ppp/peers/isp and read the parameters from there. The pppd output is redirected to the /dev/tty6 console which I use for logging system messages.

This is a sample configuration file. Please note you need to enter the user name to log on to your ISP.

# PPPD configuration options for ISP
/dev/ttyS0
115200
noauth
modem
crtscts
lock
defaultroute
noipdefault
usepeerdns
ipcp-accept-local
ipcp-accept-remote
connect "/usr/sbin/chat -v -f /etc/ppp/peers/isp.script"
mtu 1500
mru 1500
demand
asyncmap 0
idle 1200
name "your_username_here"

I won't go into all those parameters, they are sufficiently documented in the man pages and the PPP-HOWTO. A few comments though: the keyword "demand" causes pppd to wait in the background for any traffic on the ppp interface. Whenever the system wants to send a package, pppd will dial up to the isp. The connection will be automatically terminated after a certain idle period. The idle period is specified in seconds by the "idle" parameter. Another important parameter is "connect". It specifies a commandline that is being executed to connect to the isp. The purpose is to handle all activities required to automatically log on to the isp short of the user authentication. In this case we execute the program "chat" with verbous output and the script file /etc/ppp/peers/isp.script. The script file contains parameters like TIMEOUT and ABORT, as well as pairs of strings. The intended purpose is for chat to wait for the first string of a pair and then send the second string in response. Please note that you need to enter the dial up number of your ISP.

TIMEOUT 60
ABORT ERROR
ABORT BUSY
ABORT "NO CARRIER"
ABORT "NO DIALTONE"
"" ATH0X3M0L0S11=40
OK ATDT<dial_up_no_here>
CONNECT "\d\c"

The user authorisation is handled by pppd via the file /etc/ppp/pap-secrets which contains username, server and password in clear text. Because of that the file permission should usually be very restrictive like 600. Note that individual file permissions are not possible on a CD-ROM file system...

How to configure NAT

The network address translation functionality is part of the Linux kernel itself. For details please refer to the IP-Masquerade-HOWTO and the netfilter-HOWTO. I am only going to describe the basics here.

Since NAT or Masquerading (which is the Linux term for roughly the same thing) is a kernel function, it should come as no surprise that you need kernel support. In particular you should enable at least the following kernel options: CONFIG_PROC_FS, CONFIG_SYSCTL, CONFIG_NET, CONFIG_INET, CONFIG_NETFILTER, CONFIG_IP_NF_IPTABLES, CONFIG_IP_NF_FILTER.

Most guides to packet filtering under Linux are actually quite confusing, as are the plethora of tables and chains and the options of the iptables command. It is only when you look into the kernel source code that you begin to appreciate the simplicity of the design.

Let's have a look at the path of packets on their way through the kernel. The most fundamental insight is that there are five points through which packets must travel. Each of these points is called a "hook", because kernel modules can register themselves for these hooks with a certain priority. Once a packet arrives at such a hook, it will be processed by the corresponding kernel modules according to their registered priority.

Netfilter Hooks

The relevant kernel modules in our context are those for the standard tables "nat" and "filter". These are implicitely enabled by the aforementioned kernel options. Other kernel options can enable support for a table called "mangle". However, it is not needed for our purpose.

In the following picture we can see which chain is processed by which hook:

Netfilter Tables

Before IP forwarding can be used, they need to be explicitely switched on at runtime. This may have been designed this way for security reasons. Simply execute the following in one of the startup scripts:

# IP packet forwarding
if [ -f /proc/sys/net/ipv4/ip_forward ]; then
  echo "Activating IPv4 packet forwarding."
  echo 1 > /proc/sys/net/ipv4/ip_forward
else
  echo "Failed to set up IPv4 packet forwarding."
fi

In order to use NAT we need to do one more thing. Assuming all IP chains are empty and with default policy ACCEPT, we need to set up a single firewall rule:

/usr/sbin/iptables -t nat -A POSTROUTING -o ppp+ -j MASQUERADE

How to configure the firewall

The firewall functionality is also part of the Linux kernel. In fact, the NAT function is a subset of the firewall functionality. Since you have already enabled all necessary kernel modules for NAT it is only a matter of setting up a few more firewall rules. For details, there is a Firewall-HOWTO, a netfilter-HOWTO and an IPCHAINS-HOWTO. In addition, there are a lot of guides about firewalls all over the internet.

Essentially a firewall needs to be tailored to your particular needs and your particular network configuration. I shall give you a subset of my firewall rules to give you an idea. Use at own risk. ;)

#!/bin/sh
# Start/stop/restart/open the firewall.
#
# Martin Rogge, 30/07/2002
#

firewall_start() {

echo  "Starting firewall."

#--------------------------------------------------------------
# disable network during setup
#--------------------------------------------------------------

# default policies
/usr/sbin/iptables -t nat -P PREROUTING DROP
/usr/sbin/iptables -t nat -P OUTPUT DROP
/usr/sbin/iptables -t nat -P POSTROUTING DROP
/usr/sbin/iptables -t filter -P INPUT DROP
/usr/sbin/iptables -t filter -P FORWARD DROP
/usr/sbin/iptables -t filter -P OUTPUT DROP

# flush chains
/usr/sbin/iptables -t nat -F
/usr/sbin/iptables -t filter -F

#--------------------------------------------------------------
# rules for table nat chain PREROUTING
#--------------------------------------------------------------

#--------------------------------------------------------------
# rules for table filter chain FORWARD
#--------------------------------------------------------------

# experimental support for active ftp
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 20 --dport 1024: -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 20 -j ACCEPT

# deny attempts to establish TCP connections from outside
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -p tcp --syn -j DROP

# TCP ---------------------------------------------------------

# accept TCP traffic from the LAN - service requests
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 21 -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 25 -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 80 -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 110 -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 119 -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 443 -j ACCEPT

# accept TCP traffic from the LAN - game support
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p tcp --sport 1024: --dport 1024: -j ACCEPT

# accept TCP traffic from outside - service replies
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 21 --dport 1024: -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 25 --dport 1024: -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 80 --dport 1024: -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 110 --dport 1024: -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 119 --dport 1024: -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 443 --dport 1024: -j ACCEPT

# accept TCP traffic from outside - game support
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p tcp --sport 1024: --dport 1024: -j ACCEPT

# UDP ---------------------------------------------------------

# accept UDP traffic from the LAN - DNS requests
#/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p udp --sport 1024: --dport 53 -j ACCEPT

# accept UDP traffic from the LAN - game support
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p udp --sport 1024: --dport 1024: -j ACCEPT

# accept UDP traffic from outside - DNS replies
#/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p udp --sport 53 --dport 1024: -j ACCEPT

# accept UDP traffic from outside - game support
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p udp --sport 1024: --dport 1024: -j ACCEPT

# ICMP --------------------------------------------------------

# accept ICMP traffic from the LAN - certain types only:
/usr/sbin/iptables -t filter -A FORWARD -i eth+ -o ppp+ -p icmp --icmp-type 8 -j ACCEPT

# accept ICMP traffic from outside - certain types only:
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p icmp --icmp-type 0 -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p icmp --icmp-type 3 -j ACCEPT
/usr/sbin/iptables -t filter -A FORWARD -i ppp+ -o eth+ -p icmp --icmp-type 11 -j ACCEPT

#--------------------------------------------------------------
# rules for table filter chain INPUT
#--------------------------------------------------------------

# deny attempts to establish TCP connections from outside
/usr/sbin/iptables -t filter -A INPUT -i ppp+ -p tcp --syn -j DROP

# loopback device
/usr/sbin/iptables -t filter -A INPUT -i lo -j ACCEPT

# TCP ---------------------------------------------------------

# accept TCP traffic from the LAN - services
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p tcp --dport 20:21 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p tcp --dport 23 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p tcp --dport 53 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p tcp --sport 20:21 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p tcp --sport 23 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p tcp --dport 137:139 -j ACCEPT

# accept TCP traffic from the LAN - passive ftp
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p tcp --sport 1024: --dport 65000: -j ACCEPT

# accept TCP traffic from outside
/usr/sbin/iptables -t filter -A INPUT -i ppp+ -p tcp --sport 53 --dport 1024: -j ACCEPT

# UDP ---------------------------------------------------------
A
# accept UDP traffic from the LAN
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p udp --dport 53 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p udp --dport 137:139 -j ACCEPT

# accept UDP traffic from outside
/usr/sbin/iptables -t filter -A INPUT -i ppp+ -p udp --sport 53 --dport 1024: -j ACCEPT

# ICMP --------------------------------------------------------

# accept ICMP traffic from the LAN - all types
/usr/sbin/iptables -t filter -A INPUT -i eth+ -p icmp -j ACCEPT

# accept ICMP traffic from outside - certain types only
/usr/sbin/iptables -t filter -A INPUT -i ppp+ -p icmp --icmp-type 0 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i ppp+ -p icmp --icmp-type 3 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i ppp+ -p icmp --icmp-type 8 -j ACCEPT
/usr/sbin/iptables -t filter -A INPUT -i ppp+ -p icmp --icmp-type 11 -j ACCEPT

#--------------------------------------------------------------
# rules for table nat chain OUTPUT
#--------------------------------------------------------------

#--------------------------------------------------------------
# rules for table filter chain OUTPUT
#--------------------------------------------------------------

# loopback device
/usr/sbin/iptables -t filter -A OUTPUT -o lo -j ACCEPT

# TCP ---------------------------------------------------------

# accept TCP traffic to the LAN - services
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p tcp --sport 20:21 -j ACCEPT
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p tcp --sport 23 -j ACCEPT
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p tcp --sport 53 -j ACCEPT
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p tcp --dport 20:21 -j ACCEPT
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p tcp --dport 23 -j ACCEPT
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p tcp --sport 137:139 -j ACCEPT

# accept TCP traffic to the LAN - passive ftp
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p tcp --sport 65000: --dport 1024: -j ACCEPT

# accept TCP traffic to outside
/usr/sbin/iptables -t filter -A OUTPUT -o ppp+ -p tcp --sport 1024: --dport 53 -j ACCEPT

# UDP ---------------------------------------------------------

# accept UDP traffic to the LAN
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p udp --sport 53 -j ACCEPT
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p udp --sport 137:139 -j ACCEPT

# accept UDP traffic to outside
/usr/sbin/iptables -t filter -A OUTPUT -o ppp+ -p udp --sport 1024: --dport 53 -j ACCEPT

# ICMP --------------------------------------------------------

# accept ICMP traffic to the LAN - all types
/usr/sbin/iptables -t filter -A OUTPUT -o eth+ -p icmp -j ACCEPT

# accept ICMP traffic to outside - all types
/usr/sbin/iptables -t filter -A OUTPUT -o ppp+ -p icmp -j ACCEPT

#--------------------------------------------------------------
# rules for table nat chain POSTROUTING
#--------------------------------------------------------------

# masquerade
/usr/sbin/iptables -t nat -A POSTROUTING -o ppp+ -j MASQUERADE

#--------------------------------------------------------------
# switch on firewall
#--------------------------------------------------------------

# default policies
/usr/sbin/iptables -t nat -P POSTROUTING ACCEPT
/usr/sbin/iptables -t nat -P OUTPUT ACCEPT
/usr/sbin/iptables -t nat -P PREROUTING ACCEPT

}

firewall_stop() {

echo  "Stopping firewall. Network shut down."

# default policies - disable network
/usr/sbin/iptables -t nat -P PREROUTING DROP
/usr/sbin/iptables -t nat -P OUTPUT DROP
/usr/sbin/iptables -t nat -P POSTROUTING DROP
/usr/sbin/iptables -t filter -P INPUT DROP
/usr/sbin/iptables -t filter -P FORWARD DROP
/usr/sbin/iptables -t filter -P OUTPUT DROP

# flush chains
/usr/sbin/iptables -t nat -F
/usr/sbin/iptables -t filter -F

}

firewall_open() {

echo  "Opening up firewall. Security level ZERO."

# default policies - accept all
/usr/sbin/iptables -t nat -P PREROUTING ACCEPT
/usr/sbin/iptables -t nat -P OUTPUT ACCEPT
/usr/sbin/iptables -t nat -P POSTROUTING ACCEPT
/usr/sbin/iptables -t filter -P INPUT ACCEPT
/usr/sbin/iptables -t filter -P FORWARD ACCEPT
/usr/sbin/iptables -t filter -P OUTPUT ACCEPT

# flush chains
/usr/sbin/iptables -t nat -F
/usr/sbin/iptables -t filter -F

# masquerade
/usr/sbin/iptables -t nat -A POSTROUTING -o ppp+ -j MASQUERADE


}

case "$1" in
'start')
  firewall_start
  ;;
'stop')
  firewall_stop
  ;;
'restart')
  firewall_start
  ;;
'open')
  firewall_open
  ;;
*)
  echo "usage: rc.firewall start|stop|restart|open"
esac

How to set up DNS

In order to provide DNS service to the LAN there are two fundamentally different options. The first option is to open port 53 in the firewall for forwarding requests to and from the internet. That way each cient can transparently access the DNS servers of the ISP as if the client was connected directly to the internet.

The other option is to set up a DNS server on the router machine that forwards DNS requests to the internet. If the DNS server caches the responses, this option will cut down on response time to repeated DNS requests. There is a number of DNS servers out there that can be used. The classic one is BIND. One drawback of BIND is the complicated syntax of the parameter files. This problem is alleviated to some extent by the excellent DNS-HOWTO.

The basic configuration file /etc/named.conf I am using does two things: firstly it forwards DNS requests to the internet, typically to the DNS servers of the ISP. Secondly it sets up a small zone that provides domain names within the LAN. To that end it defines the translation of domain names as well as the reverse lookup of the subnets 127.0.0.* and 192.168.157.*.

options {
        directory "/var/named" ;
        forwarders
                {
                "enter IP of DNS server 1" ;
                "enter IP of DNS server 1" ;
        } ;
        query-source address * port * ;
        dialup yes ;
} ;

zone "." IN {
        type hint ;
        file "/etc/named/root" ;
} ;

zone "0.0.127.in-addr.arpa" IN {
        type master ;
        notify no ;
        file "/etc/named/127.0.0" ;
} ;

zone "157.168.192.in-addr.arpa" IN {
        type master ;
        notify no ;
        file "/etc/named/192.168.157" ;
} ;

zone "home" IN {
        type master ;
        notify no ;
        file "/etc/named/home" ;
} ;

The configuration file includes another four files that are located in folder /etc/named/. This is not standard in any known Linux distro, but my personal setup. The first one of these files, /etc/named/root, specifies the root name servers of the internet. This file should be part of any distro, although under a different name in a different location.

;       This file holds the information on root name servers needed to
;       initialize cache of Internet domain name servers
;       (e.g. reference this file in the "cache  .  <file>"
;       configuration file of BIND domain name servers).
;
;       This file is made available by InterNIC registration services
;       under anonymous FTP as
;           file                /domain/named.root
;           on server           FTP.RS.INTERNIC.NET
;       -OR- under Gopher at    RS.INTERNIC.NET
;           under menu          InterNIC Registration Services (NSI)
;              submenu          InterNIC Registration Archives
;           file                named.root
;
;       last update:    Aug 22, 1997
;       related version of root zone:   1997082200
;
;
; formerly NS.INTERNIC.NET
;
.                        3600000  IN  NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4
;
; formerly NS1.ISI.EDU
;
.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     128.9.0.107
;
; formerly C.PSI.NET
;
.                        3600000      NS    C.ROOT-SERVERS.NET.
C.ROOT-SERVERS.NET.      3600000      A     192.33.4.12
;
; formerly TERP.UMD.EDU
;
.                        3600000      NS    D.ROOT-SERVERS.NET.
D.ROOT-SERVERS.NET.      3600000      A     128.8.10.90
;
; formerly NS.NASA.GOV
;
.                        3600000      NS    E.ROOT-SERVERS.NET.
E.ROOT-SERVERS.NET.      3600000      A     192.203.230.10
;
; formerly NS.ISC.ORG
;
.                        3600000      NS    F.ROOT-SERVERS.NET.
F.ROOT-SERVERS.NET.      3600000      A     192.5.5.241
;
; formerly NS.NIC.DDN.MIL
;
.                        3600000      NS    G.ROOT-SERVERS.NET.
G.ROOT-SERVERS.NET.      3600000      A     192.112.36.4
;
; formerly AOS.ARL.ARMY.MIL
;
.                        3600000      NS    H.ROOT-SERVERS.NET.
H.ROOT-SERVERS.NET.      3600000      A     128.63.2.53
;
; formerly NIC.NORDU.NET
;
.                        3600000      NS    I.ROOT-SERVERS.NET.
I.ROOT-SERVERS.NET.      3600000      A     192.36.148.17
;
; temporarily housed at NSI (InterNIC)
;
.                        3600000      NS    J.ROOT-SERVERS.NET.
J.ROOT-SERVERS.NET.      3600000      A     198.41.0.10
;
; housed in LINX, operated by RIPE NCC
;
.                        3600000      NS    K.ROOT-SERVERS.NET.
K.ROOT-SERVERS.NET.      3600000      A     193.0.14.129
;
; temporarily housed at ISI (IANA)
;
.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     198.32.64.12
;
; housed in Japan, operated by WIDE
;
.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33
; End of File

The file /etc/named/127.0.0 defines the reverse lookup for localhost.

$TTL 3D
@       IN      SOA     tristan.home hostmaster.home. (
                        20021001        ; Serial
                        8H              ; Refresh
                        2H              ; Retry
                        4W              ; Expire
                        1D)             ; Minimum TTL
                NS      tristan.home.
1               PTR     localhost

The file /etc/named/192.168.157 defines the reverse lookup for the domain "home".

$TTL 3D
@       IN      SOA     tristan.home hostmaster.home. (
                        20021002        ; Serial
                        8H              ; Refresh
                        2H              ; Retry
                        4W              ; Expire
                        1D)             ; Minimum TTL
                NS      tristan.home.
1               PTR     jan
2               PTR     karolin
3               PTR     zorro
4               PTR     fred
5               PTR     tristan
6               PTR     arnold

The file /etc/named/home defines the host names within the domain "home".

$TTL 3D
@       IN      SOA     tristan.home hostmaster.home. (
                        20021003        ; Serial
                        8H              ; Refresh
                        2H              ; Retry
                        4W              ; Expire
                        1D)             ; Minimum TTL
                NS      tristan.home.

localhost       A       127.0.0.1

jan             A       192.168.157.1
j               CNAME   jan

karolin         A       192.168.157.2
k               CNAME   karolin

zorro           A       192.168.157.3
z               CNAME   zorro

fred            A       192.168.157.4
f               CNAME   fred

tristan         A       192.168.157.5
t               CNAME   tristan

arnold          A       192.168.157.6
a               CNAME   arnold

How to set up telnet

Telnet is one of the archetypal internet services. The telnet server is usually started from the internet daemon inetd whenever there is a request on port 23. To that end inetd must be started in one of the startup scripts, and the following line must be present in /etc/inetd.conf:

telnet  stream  tcp     nowait  root    /usr/sbin/in.telnetd    in.telnetd

For added security, sometimes in.telnetd is not called directly but through the tcp port wrapper tcpd:

telnet  stream  tcp     nowait  root    /usr/sbin/tcpd          in.telnetd

It is then possible to specify further which hosts may use what service using the configuration files /etc/hosts.allow etc. However, for the CD-ROM based router I prefer to call as few programs as possible, and the firewall provides sufficient security in a small LAN.

How to set up ftp

The ftp server is invoked from inetd in a way very similar to telnet. Just add the following line to /etc/inetd.conf:

ftp     stream  tcp     nowait  root    /usr/sbin/proftpd       proftpd

In addition to that, the ftp server itself (here proftpd) needs to be configured. This is done in /etc/proftpd.conf:

# ProFTPD configuration file.
#
# Martin Rogge, 30/07/2002

ServerName			"ProFTPD"
ServerType			inetd
DefaultServer			on
Port				21
Umask				022

MaxInstances			10

User				nobody
Group				nogroup

RootLogin			on

UseReverseDNS			off
IdentLookups			off

PassivePorts			65000 65535

SystemLog			/var/log/proftpd.log
TransferLog			/var/log/xferlog

<Directory /*>
  AllowOverwrite		on
</Directory>

<Anonymous ~ftp>
  RequireValidShell		off
  User				ftp
  Group				ftp
  UserAlias			anonymous ftp
  MaxClients			10
  DisplayLogin			welcome.msg
  DisplayFirstChdir		.message
  <Limit WRITE>
    DenyAll
  </Limit>
</Anonymous>

The configuration options are plenty and it is not possible for me to give a comprehensive explanation here. The configuration file above assumes the existence of certain users and groups, like nobody:nogroup and ftp:ftp. Please note that some options (like RootLogin) have an impact on security and should only be allowed in well secured networks.

Another option to take notice of is the definition of ports for passive ftp. These need to be reflected in the firewall configuration.

How to set up the SMB protocol

The SMB protocol is the network sharing protocol in the Windows world. It is only required if you want to do peer-to-peer networking with Windows machines. This may be practical from a maintenance point of view, but is not normally a good idea for an internet router. The relevant services are provided by the Samba package. Once again I would suggest to invoke them from the internet daemon inetd:

netbios-ssn     stream  tcp     nowait  root    /usr/sbin/smbd  smbd
netbios-ns      dgram   udp     wait    root    /usr/sbin/nmbd  nmbd

Samba itself is configured in /etc/samba/smb.conf or similar. Samba has a reputation of having an incredible number of configuration options and the study of the SMB-HOWTO and other tutorials is highly recommended. For simple purposes the following can be used. Note that this example defines a share "anybody" which is tied to user "anybody". For convenience (and to mimick a typical Windows setup) you could create a share for user root, starting in the root directory. Of course this will open root access to the whole file system and is only advisable in a very secure environment.

[global]
   workgroup = HOME
   server string = Samba Server
   hosts allow = 192.168.157. 127.
   load printers = no
   log file = /var/log/samba.%m
   max log size = 50
   security = user
   ssl CA certDir = /etc/ssl/certs
   socket options = TCP_NODELAY IPTOS_LOWDELAY
   dns proxy = no


[anybody]
   comment = All files
   path = /home/anybody
   valid users = anybody
   public = no
   writable = yes
   printable = no
   case sensitive = yes
   default case = lower
   preserve case = yes
   short preserve case = yes

A source of everlasting annoyance is the password encryption. I have chosen not to use password encryption in my Windows network, however most people will want to configure it the other way because that is the Windows default, and of course promises higher security. For details, once again I refer to the SMB-HOWTO.

A word on security

As I have now mentioned a few times, there is a trade off between convenience and security. Initially when I was experimenting a lot, it was handy to have SMB access to the files on the router. Since then I haven't used it anymore. For everyday use all I really need is a way to log on to the router and maybe transfer the odd file. This can be done using SSH in a more secure fashion. Therefore I will move to SSH with the next version of my internet router.

It goes without saying that you should remove all unused services from /etc/inetd.conf. In case you are not planning to offer any services at all, make sure you don't start inetd from the startup scripts in the first place.