Living on the Edge
Arthur Donkers
In this implementation of the security column, I will investigate the security-related features in the new 2.1.xxx Linux kernel. The odd-numbered Linux kernel versions are always considered development kernels and contain new features. Due to their nature, these kernels change very rapidly, and it is sometimes considered living on the edge if you keep up with these version numbers. (If you really want to live on the brink, consider subscribing to the kernel development mailing list; that's where the really new stuff comes from.)
As of this writing, the 2.1.125 kernel is considered the edge, but when you read this article, this version will have long been overhauled. Perhaps even replaced by the long-awaited 2.2.x kernel.
Linux Security Features Before concentrating on the new features in the Linux kernel, let us first look at the features as they are available in the 2.0.x kernel series (especially the later incarnations like 2.0.34 and 2.0.35).
The single most important feature is the firewalling code. As the name states, you can use this code for building a firewall with a Linux machine. By equipping your machine with two Ethernet cards, or an Ethernet card and a dial-up connection (be it ISDN or analog), you can connect a local network to the Internet. To do this in a (relatively) secure way, Linux offers a number of options for controlling the traffic between your local network and the Internet.
Using the firewalling code, you can specify which network packets are accepted and rejected by the firewall. Then, you can build a so-called packet filtering firewall. A packet filtering firewall looks at the network traffic and decides, based on the specified rules, whether to accept or reject this traffic. These rules are based on the direction of the network traffic and allow you to accept or reject incoming traffic, outgoing traffic, and traffic that is forwarded between two network interfaces.
As an added bonus, the forwarding rules allow you to specify a masquerading option. This masquerading option will replace the source address in the outgoing packet with the address of the external interface. Thus, all traffic appears to be originating from the external interface of the firewall. You can use this option if you want to hide the addresses of the internal network, either because you are using an invalid address range, or simply because you do not want to make your local addresses public.
Another related feature is the transparent proxying option. As you may know from configuring a Web browser, a proxy is a machine acting as an intermediate between the browser and the Internet. To be able to use a proxy, you must have a client application that understands the concept of a proxy, and that is able to be configured for using a proxy. Currently, a Web browser is the only application that can use a proxy.
Linux, however, offers an alternative. By using a Linux machine as a gateway and enabling the transparent proxy, you can address an external system just like you would when no proxy was present. Then the Linux machine will deliver those network packets to a user-specified proxy program running on the Linux machine. This works not only for Web connections, but for any TCP- or UDP-based traffic. So, without specifying a proxy in your client, you can use the proxy program on the Linux machine, completely transparently.
New or Changed Features Now that we have an idea of the available features in the 2.0.x kernel series, let us look at the 2.1.x series (especially the ones like 2.1.125 and up). By looking at the kernel configuration normally done before building a kernel, we will see the new or improved features step by step.
By doing a make config in the kernel source tree, we will be asked a number of questions related to the configuration of the Linux kernel. Below, I have highlighted the options related to the security features.
#
# Using defaults found in arch/i386/defconfig
#
*
* Code maturity level options
*
Prompt for development and/or incomplete code/drivers (CONFIG_EXPERIMENTAL)
[N/y/?] y
We must first enable the experimental code and drivers to be able to configure most of the new features. If disabled, most configuration options related to these new features are not available when configuring the kernel.
*
* Loadable module support
*
Enable loadable module support (CONFIG_MODULES) [Y/n/?]
Set version information on all symbols for modules (CONFIG_MODVERSIONS)
[N/y/?] y
Kernel module loader (CONFIG_KMOD) [N/y/?] y
*
* General setup
*
Networking support (CONFIG_NET) [Y/n/?]
This is another useful feature, since you can build most of these options directly into the kernel or as modules you can load at runtime. If you want to build the features as loadable modules, you must enable the loadable module support in the kernel. By enabling the kernel module loader, you can even have these modules loaded automatically when the kernel needs them. It needs no further explanation why you must enable networking support.
After these necessary general options, let us now take a look at the different security features and explain what you can do with these.
*
* Networking options
*
Packet socket (CONFIG_PACKET) [Y/m/n/?] ?
CONFIG_PACKET:
The Packet protocol is used by applications which communicate
directly with network devices without an intermediate network
protocol implemented in the kernel, e.g. tcpdump. If you want them
to work, choose Y. This driver is also available as a module called
af_packet.o ( = code which can be inserted in and removed from the
running kernel whenever you want). If you want to compile it as a
module, say M here and read Documentation/modules.txt. If unsure,
say Y.
The packet socket options allows you to communicate directly with the networking device (as explained by the help option of this feature). Normally, access to a networking device is controlled by the kernel. It will receive a packet from the device, and the different networking layers in the kernel will process this packet. However, there are circumstances under which you would like direct access to the packet as received from the networking device. If you want to monitor the network for illegal packets or detect portscans, for example, you need this direct access. Also, if you want to construct your own network packets (e.g., for a network security audit) you build this packet into your program and send it onto the network via this direct access device. So, it can be used both in looking at the network and sending packets on the network. (Note, this feature can also be misused when you want to construct illegal packets and use them to try to hack your way into a computer.)
Kernel/User netlink socket (CONFIG_NETLINK) [N/y/?] ?
CONFIG_NETLINK:
This driver allows for two-way communication between certain parts
of the kernel or modules and user processes; the user processes are
able to read from and write to character special files in the /dev
directory having major mode 36. So far, the kernel uses it to
publish some network-related information if you say Y to "Routing
messages", below. It is also used by the firewall code to publish
information about possible attacks if you say Y to "IP: firewall
packet netlink device" further down. You also need to say Y here if
you want to use arpd, a daemon that helps keep the internal ARP
cache (a mapping between IP addresses and hardware addresses on the
local network) small. The ethertap device, which lets user space
programs read and write raw Ethernet frames, also needs the network
link driver. If unsure, say Y.
You should enable this option if you want to use certain features in the kernel. What this feature provides is a way for the kernel to communicate directly with programs in "userland" and vice versa. The kernel will use this link for sending network packets to a userland program, or internal kernel data. All of these communications are done via special device files. Some of these device files only allow you to read data from the kernel; other devices establish a two-way communications channel. In the next few examples, we will see some specific applications for this option.
Routing messages (CONFIG_RTNETLINK) [N/y/?] (NEW) ?
CONFIG_RTNETLINK:
If you say Y here and create a character special file /dev/route
with major number 36 and minor number 0 using mknod ("man mknod"),
you (or some user space utility) can read some network-related
routing information from that file. Everything you write to that
file will be discarded.
This is the first option that uses the CONFIG_NETLINK feature. The kernel will deliver routing information to the device with the major number 36 and minor number 0. By writing a program that opens this device file, and reading from it, you will get routing information straight from the kernel. If you have a PPP-based Internet link, you will receive a message on this device whenever your PPP connection to the Internet is established (and you have enabled the defaultrouter option in the PPP configuration). You can also use this for checking unexpected changes to the routing table in the kernel.
Network firewalls (CONFIG_FIREWALL) [N/y/?] y
This option enables the venerable firewalling option in the kernel. Although this feature is well known from the 2.0.x kernel, from 2.1.102 onward, you can no longer use the ipfwadm program to configure this feature. You must now use ipchains, which offers a superset of the ipfwadm features. Below is an overview of the features of the ipchains program.
ipchains 1.3.8, 27-Oct-1998
Usage: ./ipchains -[ADC] chain rule-specification [options]
./ipchains -[RI] chain rulenum rule-specification [options]
./ipchains -D chain rulenum [options]
./ipchains -[LFZNX] [chain] [options]
./ipchains -P chain target [options]
./ipchains -M [ -L | -S ] [options]
./ipchains -h [icmp] (print this help information, or ICMP list)
Commands:
Either long or short options are allowed.
-add -A chain Append to chain
-delete -D chain Delete matching rule from chain
-delete -D chain rulenum Delete rule rulenum (1 = first) from chain
-insert -I chain [rulenum] Insert in chain as rulenum (default 1=first)
-replace -R chain rulenum Replace rule rulenum (1 = first) in chain
-list -L [chain] List the rules in a chain or all chains
-flush -F [chain] Delete all rules in chain or all chains
-zero -Z [chain] Zero counters in chain or all chains
-check -C chain Test this packet on chain
-new -N chain Create a new user-defined chain
-delete -X chain Delete a user-defined chain
-policy -P chain target Change policy on chain to target
-masquerade -M -L List current masqerading connections
-masquerade -M -S tcp tcpfin udp Set masquerading timeout values
Options:
-bidirectional -b insert two rules: one with -s & -d reversed
-proto -p [!] proto protocol: by number or name, eg. 'tcp'
-source -s [!] address[/mask] [!] [port[:port]]
source specification
-source-port [!] [port[:port]]
source port specification
-destination -d [!] address[/mask] [!] [port[:port]]
destination specification
-destination-port [!] [port[:port]]
destination port specification
-icmp-type [!] typename specify ICMP type
-interface -i [!] name[+]
network interface name ([+] for wildcard)
-jump -j target [port] target for rule ([port] for REDIRECT)
-mark -m [+-]mark number to mark on matching packet
-numeric -n numeric output of addresses and ports
-log -l turn on kernel logging for matching packets
-output -o [maxsize] output matching packet to netlink device
-TOS -t and xor and/xor masks for TOS field
-verbose -v verbose mode
-exact -x expand numbers (display exact values)
[!] -fragment -f match second or further fragments only
[!] -syn -y match TCP packets only when SYN set
[!] -version -V print package version.
If you are familiar with the ipfwadm program, you will see all the familiar options, plus a few extras. First of all, in the "old" firewall feature, there was one table for all network traffic. With the new kernel and ipchains, you can define chains of filter rules and link these to ports or devices. So, you can build independent chains for each specific purpose. With the ipchains program, you can now also specify rules for ICMP traffic. You can block or accept specific ICMP functions (e.g., ECHO and ECHO REPLY to enable ping through the firewall and block all others, like REDIRECT). You can also specify rules that apply to fragments of the traffic you received.
If we go back to the kernel options, we can take a look at the next security feature.
Socket Filtering (CONFIG_FILTER) [N/y/?] ?
CONFIG_FILTER:
The Linux Socket Filter is derived from the Berkeley Packet Filter.
If you say Y here, user-space programs can attach a filter to any
socket and thereby tell the kernel that it should allow or disallow
certain types of data to get through the socket. Linux Socket
Filtering works on all socket types except TCP for now. See the text
file linux/Documentation/networking/filter.txt for more information.
If unsure, say N.
With this option, you can build (in C) a function that checks a packet and returns true or false depending on the function you wrote. You can "link" this filter function to the network socket, and all subsequent traffic will be processed by the filter before being delivered to the application that opened this socket. You can also unlink this function.
IP: firewalling (CONFIG_IP_FIREWALL) [N/y/?] (NEW) y
IP: firewall packet netlink device (CONFIG_IP_FIREWALL_NETLINK) [N/y/?] (NEW)
?
CONFIG_IP_FIREWALL_NETLINK:
If you say Y here, then the first 128 bytes of each packet that hit
your Linux firewall and were blocked are passed on to optional user
space monitoring software that can then look for attacks and take
actions such as paging the administrator of the site.
To use this, you need to create a character special file under /dev
with major number 36 and minor number 3 using mknod ("man mknod"),
and you need (to write) a program that reads from that device and
takes appropriate action.
With the ipchains tool, you can specify which packets you want to go
to this device, as well as how many bytes from each packet.
This option can be very useful in detecting break-in attempts. It also uses a special device, and all packets that are blocked by the kernel are sent to this device. You can write a special program that reads these packets from the device. This program can then try to determine from these packets whether someone is attempting a portscan (when within a certain period of time a number of packets arrives at unconfigured or blocked services). Illegal packets that are blocked are also delivered to this device.
The final set of options is used to forward specific traffic from the outside to a machine on the inside. You first must enable the global option and, subsequently, specific options.
IP: transparent proxy support (CONFIG_IP_TRANSPARENT_PROXY) [N/y/?] (NEW) y
IP: always defragment (CONFIG_IP_ALWAYS_DEFRAG) [N/y/?] (NEW) y
IP: masquerading (CONFIG_IP_MASQUERADE) [N/y/?] (NEW) y
*
* Protocol-specific masquerading support will be built as modules.
*
IP: ICMP masquerading (CONFIG_IP_MASQUERADE_ICMP) [N/y/?] (NEW) y
*
* Protocol-specific masquerading support will be built as modules.
*
IP: masquerading special modules support
(CONFIG_IP_MASQUERADE_MOD) [N/y/?] (NEW) ?
This enables masqueraded forwarding, either from the inside to the outside or vice versa. The next option will enable channeling connections from the outside to a specific port on an internal machine. The help text explains it further.
(CONFIG_IP_MASQUERADE_IPPORTFW) [N/y/m/?] (NEW) ?
CONFIG_IP_MASQUERADE_IPPORTFW:
Port Forwarding is an addition to IP Masquerading written by Steven
Clarke to allow some forwarding of packets from outside to inside a
firewall on given ports. This could be useful if, for example, you
want to run a web server behind the firewall or masquerading host
and this web server should be visible to the outside world. An
external client connects to port 80 of the firewall, the firewall
forwards requests to this port to the web server, the web server
handles the request, and the results are sent through the firewall to
the original client. The client thinks that the firewall machine
itself is running the web server.
Information about it is available from:
http://www.monmouth.demon.co.uk/ipsubs/portforwarding.html (to
browse the WWW, you need to have access to a machine on the Internet
that has a program like lynx or netscape). You will need the user
space program "ipmasqadm", which can be downloaded from:
http://juanjox.home.ml.org/
For general info, please see:
ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/
The final option is related to a well-known denial-of-service attack in which all sockets on a machine are quickly exhausted. By reacting to this attack by sending specific sequence numbers, you can minimize the effect of this attack.
IP: TCP syncookie support (not enabled per default) (CONFIG_SYN_COOKIES)
[N/y/?] ?
CONFIG_SYN_COOKIES:
Normal TCP/IP networking is open to an attack known as "SYN flooding".
This denial-of-service attack prevents legitimate remote users from
being able to connect to your computer and requires very little work
from the attacker, who can operate from anywhere on the Internet.
SYN cookies provide protection against this type of attack. If you
say Y here, the TCP/IP stack will use a cryptographic challenge
protocol known as "SYN cookies" to enable legitimate users to
continue to connect, even when your machine is under attack. There
is no need for the legitimate users to change their TCP/IP software;
SYN cookies work transparently to them. For technical information
about SYN cookies, check out:
ftp://koobera.math.uic.edu/pub/docs/syncookies-archive.
If you are SYN flooded, the source address reported by the kernel is
likely to have been forged by the attacker; it is only reported as
an aid in tracing the packets to their actual source and should not
be taken as absolute truth.
If you say Y here, note that SYN cookies aren't enabled by default;
you can enable them by saying Y to "/proc filesystem support" and
"Sysctl support" below and executing the command
echo 1 >/proc/sys/net/ipv4/tcp_syncookies
at boot time after the proc filesystem has been mounted.
If you want to be able to use these options, you need a number of support programs. You can find these different programs at the following locations:
ipchains http://ww.adelaide.net.au/~rustcorp/ipfwchains
ipmasqadm http://juanjox.home.ml.org
ipautofw ftp://ftp.netis.com/pub/members/rlynch
Conclusion Although Linux already offered a number of security features in the 2.0.x kernel, the new 2.1.x kernel offers a lot of interesting new features. However, most of these features are geared toward a packet filtering firewall. If you really want to be safe, you need to extend this with a number of application-based filtering proxies, preferably by making use of the transparent proxy feature. Overall, it is becoming more and more viable to use a Linux machine as your (outer) firewall for your Internet connection. Happy Linuxing.
About the Author
Arthur Donkers graduated from the Delft University of Technology with a degree in Electrical Engineering and a major in Computer Architecture. Since then he has worked for a number of major software houses in the Netherlands. His primary field of interest is in datacommunications, especially the security aspects involved. He now is the founder and owner of Le Reseau, a company specializing in security-related issues for UNIX, OpenVMS and Windows NT, and the application of Linux in corporate environments.
|