TCP/IP Stack Hardening
Modified 18 January 2010
If you run a UNIX-like operating system, you can make it more secure
by slightly modifying the behavior of its TCP/IP implementation.
This page lists modifications for the various TCP/IP protocols. For
the most part, these are commands that would go into a boot script such
as /etc/rc.sysinit or/etc/rc.local.
The tables only list the possible commands — some tuning steps are
not possible (at least as far as I know) on certain UNIX
implementations.
If there is a dangerous type of packet that might be allowed under a
strict interpretation of the protocols, but which is currently
considered to be risky, the listed commands frequently list how to both
ignore inbound packets and refuse to send outbound packets. This
prevents your host from being victimized and prevents it from being
used to launch attacks.
This page only describes how to harden the TCP/IP stack on UNIX-like
operating systems. It is based on the recommendations found in the
following pages, plus my commentary and explanation:
ARP
Decrease the ARP cache cleanup interval.
AIX |
no -o
arpt_killc=20 |
FreeBSD |
sysctl -w
net.link.ether.inet.max_age=1200 |
Solaris |
ndd -set /dev/arp arp_cleanup_interval 60000 |
Consider static ARP (but also consider the maintenance problems!). This does not scale well to
routine use on LANs, but it might be worth its trouble on a small
sensitive LAN — a DMZ LAN in your network perimeter, or a small LAN
populated by a few sensitive servers and a router port. Remember that if you change
the Ethernet card in one machine, you must then modify and re-run the
static ARP script boot script on every host on that LAN!
If you want to do this, you will need a script like the following,
with IP and MAC addresses changed as needed. For thorough paranoia,
define a MAC address for all possible IP addresses on the
LAN, even ones not in use. For the unused IP addresses, use a MAC
address that you know will not exist on that LAN (maybe that of an
Ethernet card on another LAN).
arp -s 10.1.1.1
00:02:E3:05:9F:A3
arp -s 10.1.1.2 00:08:C7:29:E7:31
arp -s 10.1.1.3 00:60:97:B9:3B:B5
... and so on ... |
ICMP
Disable ICMP broadcast echo activity. Otherwise, your system could be
used as part of a Smurf attack:
AIX |
no -o
directed_broadcast=0 |
FreeBSD |
sysctl -w
net.inet.icmp.bmcastecho=0 |
HP-UX |
ndd -set /dev/ip
ip_respond_to_echo_broadcast 0
ndd -set /dev/ip ip_forward_directed_broadcasts 0 |
IRIX |
systune
allow_brdaddr_srcaddr 0 |
Linux |
sysctl -w
net.ipv4.icmp_echo_ignore_broadcasts=1 |
OpenBSD |
Already ignores these by default |
Solaris |
ndd -set /dev/ip
ip_respond_to_echo_broadcast 0
ndd -set /dev/ip ip6_respond_to_echo_multicast 0
ndd -set /dev/ip ip_forward_directed_broadcasts 0 |
Disable ICMP routing redirects. Otherwise, your system could
have its routing table misadjusted by an attacker.
AIX |
no -o
ipignoreredirects=1
no -o ipsendredirects=0 |
FreeBSD |
sysctl -w
net.inet.ip.redirect=0
sysctl -w net.inet.ip6.redirect=0 |
HP-UX |
ndd -set /dev/ip
ip_send_redirects 0
ndd -set /dev/ip ip_forward_directed_broadcasts 0 |
IRIX |
systune
icmp_dropredirects 1 |
Linux |
sysctl -w
net.ipv4.conf.all.accept_redirects=0
sysctl -w net.ipv6.conf.all.accept_redirects=0
sysctl -w net.ipv4.conf.all.send_redirects=0
sysctl -w net.ipv6.conf.all.send_redirects=0 |
OpenBSD |
sysctl -w
net.inet.icmp.rediraccept=0
sysctl -w net.inet6.icmp6.rediraccept=0
Those two disable the acceptance of ICMP Redirect.
To disable sending ICMP Redirect messages:
sysctl -w
net.inet.ip.redirect=0
sysctl -w net.inet6.ip6.redirect=0 |
Solaris |
ndd -set /dev/ip
ip_ignore_redirect 1
ndd -set /dev/ip ip6_ignore_redirect 1
ndd -set /dev/ip ip_send_redirects 0
ndd -set /dev/ip ip6_send_redirects 0
|
Disable ICMP router solicitations and advertisements, and ICMP
subnet mask requests and replies. An
attacker might be able to use unsolicited advertisements and replies to
misadjust host routing tables. An attack also might be able to use
solicitations and requests to reverse engineer some details of your
network infrastructure. It
appears that you will have to do this with packet-filtering rules on
the host.
Disable ICMP broadcast probes. Otherwise, an attacker might be
able to reverse engineer some details of your network infrastructure.
AIX |
no -o
icmpaddressmask=0 |
FreeBSD |
sysctl -w
net.inet.icmp.maskrepl=0 |
HP-UX |
ndd -set /dev/ip ip_respond_to_address_mask_broadcast 0
ndd -set /dev/ip ip_respond_to_timestamp_broadcast 0 |
IRIX |
You will have to block these with a packet filter like ipfilterd |
Linux |
You will have to block these with a packet filter like iptables |
OpenBSD |
Already ignores these by default |
Solaris |
ndd -set /dev/ip ip_respond_to_address_mask_broadcast 0
ndd -set /dev/ip ip_respond_to_timestamp_broadcast 0 |
IP
Disable IP source routing. The
only use of IP source routing these days is by attackers trying to
spoof IP addresses that you would trust as internal hosts.
AIX |
no -o
ipsrcroutesend=0
no -o ipsrcrouteforward=0 |
FreeBSD |
sysctl -w
net.inet.ip.sourceroute=0
sysctl -w net.inet.ip.accept_sourceroute=0 |
HP-UX |
ndd -set /dev/ip
ip_src_route_forward 0 |
IRIX |
systune ipforward
2 |
Linux |
sysctl -w net.ipv4.conf.all.accept_source_route=0
sysctl -w net.ipv4.conf.all.forwarding=0
sysctl -w net.ipv4.conf.all.mc_forwarding=0 |
OpenBSD |
Already ignores these by default |
Solaris |
ndd -set /dev/ip
ip_forward_src_routed 0
ndd -set /dev/ip ip6_forward_src_routed 0 |
Enforce sanity checking, also called ingress filtering or egress
filtering. The point is
to drop a packet if the source and destination IP addresses in the IP
header do not make sense when considered in light of the physical
interface on which it arrived.
Linux |
sysctl -w
net.ipv4.conf.all.rp_filter=1 |
Log and drop "Martian" packets. A "Martian" packet is one for
which the host does not have a route back to the source IP address (it
apparently dropped in from Mars). These days most hosts have a default
route, meaning that there would be no such thing as a Martian packet,
but to be safe and complete...
Linux |
sysctl -w
net.ipv4.conf.all.log_martians=1 |
Enforce strict multi-homing for non-forwarding multi-homed
systems. If a host is
connected to more than one LAN, but it should not act as an IP router,
make certain that it does not forward IP datagrams between networks.
Maybe it is a firewall, or maybe it is just a multi-homed host.
Solaris |
ndd -set /dev/ip
ip_strict_dst_multihoming 1
ndd -set /dev/ip ip6_strict_dst_multihoming 1 |
TCP
Increase resiliance under heavy TCP load (which makes the system
more resistant to SYN Flood attacks). There are five major steps to
making a system more resiliant under heavy, possibly malicious, TCP
load:
- Buy more RAM. Each
inbound SYN packet is intended to establish a TCP circuit, which
requires resources on the server. The TCP buffers require memory to be
allocated.
- Use TCP SYN Cookies (Linux and BSD only). With TCP Syn Cookies, the kernel
does not really allocate the TCP buffers unless the server's ACK/SYN
packet gets an ACK back, meaning that it was a legitimate request.
- Reduce the allowed number of HALF_OPEN TCP circuits. Further requests are refused, a
denial of service, but at least the server hasn't run out of memory.
- Reduce the amount of time an opening TCP circuit can stay in
the HALF_OPEN state. The
server is made less patient — if the TCP circuit is not fully
established quickly, it is dropped and the client, if legitimate but
very slow, must start again.
- Reduce the amount of time a closing TCP circuit can stay in
the TIME_WAIT state. Some
clients are very rude, apparently Microsoft Explorer is particularly
bad. They establish a connection, get their data, but then refuse to
participate in cleanly shutting down the TCP circuit. At least for busy
web servers, make them very impatient with such nonsense, dropping
these no longer active connections and freeing resources.
The following show the vendor recommendations for tuning the TCP
queue length and circuit establishment timers, and how to reduce TCP
TIME_WAIT to 60 seconds.
AIX |
no -o
clean_partial_conns=1 |
FreeBSD |
sysctl -w
kern.ipc.somaxconn=1024 |
HP-UX |
ndd -set /dev/tcp
tcp_syn_rcvd_max 1024
ndd -set /dev/tcp tcp_conn_request_max 200
ndd -set /dev/tcp tcp_time_wait_interval 60000 |
IRIX |
systune tcp_2msl
60
The kernel automatically limits the queue of pending connections. |
Linux |
sysctl -w
net.ipv4.tcp_max_syn_backlog=1280
sysctl -w net.ipv4.tcp_syncookies=1
Already drops inactive TCP connections within 60 seconds |
OpenBSD |
Already has a resilient TCP implementation by default |
Solaris |
ndd -set /dev/tcp
tcp_conn_req_max_q 1024
ndd -set /dev/tcp tcp_conn_req_max_q0 4096
ndd -set /dev/tcp tcp_time_wait_interval 60000 |
Defend against TCP connection hijacking by following the
recommendations of RFC 1948. Most
UNIX implementations use RFC 1948 recommendations to generate initial
sequence numbers, but Solaris (at least up through Solaris 8) needs a
little help.
Solaris |
ndd -set /dev/tcp
tcp_strong_iss 2
To configure this behavior to be the default after future reboots, put
the line TCP_STRONG_ISS=2 in the file/etc/default/inetinit |
Increase TCP send and receive window sizes to at least 32 kbytes. But do not increase these above 64 kbytes
unless you fully understand and support both RFC 1323 and RFC 2018.
AIX |
no -o
tcp_sendspace=32768
no -o tcp_recvspace=32768 |
FreeBSD |
sysctl -w
net.inet.tcp.sendspace=32768
sysctl -w net.inet.tcp.recvspace=32768 |
HP-UX |
The TCP send and receive spaces are 32 kbytes by default. |
IRIX |
The TCP send and receive spaces are 64 kbytes by default. |
Linux |
The kernel supports RFC 1323 and RFC 2018 and dynamically
adjusts the TCP send and receive space by default |
OpenBSD |
The kernel supports RFC 1323 and RFC 2018 and dynamically
adjusts the TCP send and receive space by default |
Solaris |
ndd -set /dev/tcp
tcp_xmit_hwat 32768
ndd -set /dev/tcp tcp_recv_hwat 32768 |