Lug@GT Setting up a Firewall Securely
Presented on Sept. 14 2005 by Matt Wood (matt /at woodzy /dot com)
- Intro to netfilter/iptables - PF
- Nifty Features
- Problems
- Basic Syntax
- Simple ruleset
- Network Design
- What a firewall / packet filterer should be.
- Why a NAT is not a Firewall!
- NAT'ing Security Risks and Advantages
- QoS
- ICMP Traffic that needs to be slapped.
- Source and Destination Filtering from the INTERNAL devices
- Pedantic Security Settings *cough* OpenBSD
- Tools
Intro to some FW's
| IpTables | PF |
| Nifty Features |
- Modules
- Built-in Connection Tracking (FTP)
- Rate Limiting
- Per Rule Statistics
- EXTENSIVE Logging Features
|
- Scrub (Packet Normalization)
- Queuing Built in
- Anchors & Tables
- Rule Shorthand (Antispoof)
|
| Problems |
- AltQ
- Syntax/Grammar
- Dynamic Changes
- Hacks to Save Rules
|
- Requires 3rd Party app for connection tracking
- Some syntax isn't too intuitive
|
All in all, if you can't tell, I'm kinda partial to PF...
Example Statistics Output IPTables
woodzy@va-www ~# iptables -vnL
Chain INPUT (policy DROP 41071 packets, 1811K bytes)
pkts bytes target prot opt in out source destination
20M 3029M ACCEPT all -- eth0 * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
8415K 563M ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
0 0 DROP all -- eth0 * 127.0.0.0/8 0.0.0.0/0
0 0 DROP all -- eth0 * 192.168.0.0/24 0.0.0.0/0
0 0 DROP all -- eth0 * 10.0.0.0/8 0.0.0.0/0
15M 6661 DROP tcp -- * * 67.162.151.217 0.0.0.0/0 tcp flags:0x16/0x02
868K 45M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 flags:0x16/0x02
629 32444 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 flags:0x16/0x02
48524 2902K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 flags:0x16/0x02
7976 403K ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:25 flags:0x16/0x02
1058 63460 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:993 flags:0x16/0x02
24 1312 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:2401 flags:0x16/0x02
99881 20M DROP udp -- eth0 * 0.0.0.0/0 0.0.0.0/0
7454 298K DROP tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x16/0x02
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 9413K packets, 814M bytes)
pkts bytes target prot opt in out source destination
21M 22G ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:80
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:21
792K 128M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:22
132K 11M ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp spt:25
Example Statistics PF
root@ga /home/woodzy# pfctl -sinfo
Status: Enabled for 24 days 10:24:24 Debug: Urgent
Hostid: 0xabc896b8
Interface Stats for ne3 IPv4 IPv6
Bytes In 33188249329 128
Bytes Out 21768735045 0
Packets In
Passed 54085054 0
Blocked 4839289 2
Packets Out
Passed 54179338 0
Blocked 68 0
State Table Total Rate
current entries 1196
searches 223346490 105.8/s
inserts 5782539 2.7/s
removals 5781343 2.7/s
Counters
match 10600030 5.0/s
bad-offset 0 0.0/s
fragment 0 0.0/s
short 17 0.0/s
normalize 31 0.0/s
memory 3899 0.0/s
Basic Syntax of IPTables & PF
IPTables (A Servers Host Based Firewall)
#!/bin/bash
#Set Default
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Flush (-F) all specific rules
iptables -F INPUT
iptables -F FORWARD
iptables -F OUTPUT
iptables -F -t nat
# Permit packets in to firewall itself that are part of existing and related connections.
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow all inputs to firewall from the internal network and local interfaces
iptables -A INPUT -i lo -s 0/0 -d 0/0 -j ACCEPT
# Deny any packet coming in on the public internet interface eth0
# which has a spoofed source address from our local networks:
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/24 -j DROP
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
#block bastard
iptables -A INPUT -p tcp -s 67.162.151.217/32 -d 0/0 --syn -j DROP
# Accept all tcp SYN packets on allowed ports
#Enable http
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 80 --syn -j ACCEPT
#Enable https
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 443 --syn -j ACCEPT
#Enable remote ssh
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 22 --syn -j ACCEPT
#Enable incoming SMTP
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 25 --syn -j ACCEPT
#Enable income FTP
#iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 21 --syn -j ACCEPT
#Enable strange VNC port
#iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 31333 --syn -j ACCEPT
#Enable remote pop3s
#iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 995 --syn -j ACCEPT
#Enable remote imaps
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 993 --syn -j ACCEPT
#Enable remote cvs
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 2401 --syn -j ACCEPT
#Count some specific droppings
iptables -A INPUT -i eth0 -s 0/0 -d 0/0 -p udp -j DROP
iptables -A INPUT -i eth0 -s 0/0 -d 0/0 -p tcp --syn -j DROP
##Add this just to count our output to the world
iptables -A OUTPUT -p tcp -s 0/0 -d 0/0 --source-port 80 -j ACCEPT
iptables -A OUTPUT -p tcp -s 0/0 -d 0/0 --source-port 21 -j ACCEPT
iptables -A OUTPUT -p tcp -s 0/0 -d 0/0 --source-port 22 -j ACCEPT
iptables -A OUTPUT -p tcp -s 0/0 -d 0/0 --source-port 25 -j ACCEPT
PF (A Gateway Router/NAT Based Firewall)
root@ga /home/woodzy# cat /etc/pf.conf
# macros
int_if = "xl0"
ext_if = "ne3"
tcp_services = "{ 22,53,80 }"
udp_services = "{ 53 }"
intern_tcp_services = "{ 6880:6889, 2222 }"
intern_udp_services = "{ 6880:6889 }"
icmp_types = "echoreq"
priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"
#priv_nets="{127.0.0.0/8}"
# options
set block-policy drop
set loginterface $ext_if
set optimization normal
# scrub
scrub in all fragment reassemble
scrub out on $ext_if random-id
#queues
#altq on $ext_if priq bandwidth 100% queue { q_pri, q_bt, q_def }
#queue q_pri priority 7
#queue q_bt priority 2 priq
#queue q_def priority 5 priq(default)
# nat/rdr
nat on $ext_if from $int_if:network to any -> ($ext_if)
#BT stuff
rdr on $ext_if proto udp from any to $ext_if:0 port 6881:6889 -> 10.13.13.14 port 6881:6889
rdr on $ext_if proto tcp from any to $ext_if:0 port 6881:6889 -> 10.13.13.14 port 6881:6889
rdr on $ext_if proto tcp from any to $ext_if:0 port 2222 -> 10.13.13.14 port 2222
# filter rules
block log all
pass quick on lo0 all
#ssh blocks
block drop in quick log on $ext_if from <sshblocks> to any
#end ssh blocks
block drop in quick log on $ext_if from $priv_nets to any
block drop out quick log on $ext_if from any to $priv_nets
pass in on $ext_if inet proto tcp from any to ($ext_if) \
port $tcp_services flags S/SA
pass in on $ext_if inet proto udp from any to ($ext_if) \
port $udp_services
#pass in rules for RDR
pass in on $ext_if proto tcp from any to any \
port $intern_tcp_services keep state
pass in on $ext_if proto udp from any to any \
port $intern_udp_services
pass in inet proto icmp all icmp-type $icmp_types keep state
pass in on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state
pass out on $ext_if proto tcp all modulate state #flags S/SA queue (q_def, q_pri)
pass out on $ext_if proto { udp, icmp } all keep state
SSH Blocks Table
root@ga /home/woodzy# pfctl -tsshblocks -Tshow
24.137.111.42
61.66.208.60
61.66.208.117
61.72.102.26
61.74.67.139
61.79.228.100
61.82.137.141
61.85.239.211
61.129.49.27
61.218.8.110
61.220.244.252
62.73.5.215
.
.
.
220.70.167.67
220.95.231.111
220.194.58.118
221.113.36.252
221.115.123.27
221.166.169.102
222.45.45.132
222.88.82.76
222.118.5.179
222.122.13.23
222.237.79.237
root@ga /home/woodzy# wc -l /etc/pf.ssh.blocks
6347 /etc/pf.ssh.blocks
root@ga /home/woodzy# cat ~/scripts/ssh-failedlogin-blocker.pl
#!/usr/bin/perl
use File::Tail;
use warnings;
my $count = 0;
my @iplist =();
my @occurlist =();
my $line = "";
my $ip = 0;
my $i;
my $file = File::Tail->new(name=>"/var/log/authlog",maxinterval=>1,resetafter=>86400);
while(defined($line=$file->read))
{
if ($line =~ m/Failed password for root from ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/)
{
insertIP($1);
}
elsif ($line =~ m/Illegal user [a-zA-Z0-9]+ from ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/)
{
insertIP($1);
}
if ($i > $#iplist)
{
#print "if, added, root, ". $ip ."\n";
$iplist[$i] = $ip;
$occurlist[$i] = 1;
}
}
exit;
sub insertIP
{
$ip = $_[0];
for($i = 0; $i <= $#iplist; $i++)
{
if ($iplist[$i] eq $ip)
{
print "if, found, root ". $ip ."\n";
$occurlist[$i]++;
if ($occurlist[$i] > 5)
{
#print "already added...\n";
$orange=`pfctl -t sshblocks -T replace -f /etc/pf.ssh.blocks`
}
elsif ($occurlist[$i] > 4)
{
open(SSH_BLOCK,">> /etc/pf.ssh.blocks") or die "crap file open failed $!";
#print SSH_BLOCK "$ip\n";
$orange=`pfctl -t sshblocks -T replace -f /etc/pf.ssh.blocks`;
close(SSH_BLOCK);
}
last;
}
}
}
#vim expandtab:cin:sw=4
Network Design
Stolen from http://www.geocities.com/boothmonkey2000/variation1.gif
Stolen from http://www.geocities.com/boothmonkey2000/variation2.gif
What a firewall / packet filter should be
Why do network administrators want/need firewalls? Well I'm sure the target audience is pretty familiar
with reasons why such a device proves necessary (Kernel Flaws, Unwanted Worms, (D)Dos, Spyware, Dr. Jekyl
and Mr. Hyde problems). A firewall on a network is alot like a windshield on your car, you want to let
through the information you want (the road, lines, other cars, protons) and at the same time keep the bugs
and wind out of your eyes. But a firewall isn't perfect and should never be considered a protection against
actual threats. Going with the windsheild analogy... a metal pipe or high intensity gamma rays aren't going to be
stopped by a windshield at speed. Same goes for firewalls, a 0day for (insert daemon here... ie Apache) is gonna
plow right through any standard firewall. A firewalls true purpose is not to protect from "evil people" like the
commercial giants and media want you to think, but protect your computers from run of the mill miscreants and
your own configuration/installation mistakes. Of course a "drop all" rule is effective in protecting you from the
Internet very nicely.
Why a NAT is not a Firewall!
All these Cable/DSL NAT/Router/Crapwall/Broken POS things that are sold nowadays do some good, but do not do
nearly as much as what the consumer thinks its actually doing. In some cases these little appliances will destroy
your network through explosions and rabid penguins. But seriously stuff like: a maximum of 2k states in table,
arp irritations, foolish web interface designs, backdoors, slow processor, HUGELY vulnerable to SynFlood Attacks,
dhcp lease file corruption... they are just generally unstable. But this rant has nothing to do with actual
Network Address Translation devices... we all know what these are right? Both IPTables and PF allow for some
type of NAT to be integrated into the firewall, but by no means does the translation of addresses secure a host
on a network. (wrt54g idefense stuff... if you dont have openwrt on them your screwed)
NAT'ing Security Risks and Advantages
Advantages
- 1-N external IP addresses
- Logical seperation
- Stateless packet filtering is easier
Risks
- Std Traffic generally exposes the # and type of hosts behind the NAT
- False sense of security
- Application errors due to the NAT... require intelligence to fix/work around
QoS
This isn't too important for the standard user, but there are some optimizations that prove exceptionally useful
(especially on campus network style setups). Connections such as BitTorrent readily fill your upload and download
pipe with data,acks and leave little for for the syn's and synacks needed to setup standard connections. Such that
if you happen to be downloading the DVD Screener for 40 Year Old Virgin while wanting to ssh and surf the net,
you'll see a significant delay while opening new connections or starting to send packets (or a noticed delay in
reception of packets) because your pipe is so full.
Explanation from "http://www.benzedrine.cx/ackpri.html"
Even when a TCP connection is used to send data only in one direction (like when downloading a file through ftp), TCP acknowledgements (ACKs) must be sent in the opposite direction, or the peer will assume that its packets got lost and retransmit them. To keep the peer sending data at the maximum rate, it's important to promptly send the ACKs back.
When the uplink is saturated by other connections (like a concurrent upload), all outgoing packets get delayed equally by default. Hence, a concurrent upload saturating the uplink causes the outgoing ACKs for the download to get delayed, which causes the drop in the download throughput.
The basic PF ruleset that accomplishes something similiar with BitTorrent queuing added this looks like the following...
ext_if="interfaceName"
altq on $ext_if priq bandwidth $BWUpload queue { std_que, bt_que, ack_out }
queue ack_out priority 7
queue bt_que priority 1
queue std_que priority 3 priq(default)
pass out on $ext_if proto tcp from $ext_if to any port 6881:6889 flags S/SA keep state queue (bt_que, ack_out)
pass out on $ext_if proto tcp from $ext_if to any flags S/SA keep state queue (std_que, ack_out)
pass in on $ext_if proto tcp from any to $ext_if port 6881:6889 flags S/SA keep state queue (bt_que, ack_out)
pass in on $ext_if proto tcp from any to $ext_if flags S/SA keep state queue (std_que, ack_out)
ICMP Traffic that needs to be slapped
Basic rule here is drop everything you don't specifically care about. The only type of ICMP message I allow through
my firewalls is echoreq everything else is dropped before it crosses the FW. Some other types that I generally
allow to reach the firewall itself are ICMP message types such as "host/port-unreachable." Alot of other types are
generally do not need to really be worried about, and 5 of the 17 types are more useful for DoS attacks than helpful
in indenfication of errors.
Source and Destination Filtering from the INTERNAL Devices
What that title means is you really want to have rules that specifically allow traffic EXITing and ENTERing...
none of this ESTABLISHED/RELATED and allow all packets on the inside out. It does negate some of the usefulness of
the firewall.
For Example...
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 80 --syn -j ACCEPT
iptables -A OUTPUT -p tcp -s 0/0 -d 0/0 --source-port 80 -j ACCEPT
block drop in all
block drop out all
pass in on $ext_if inet proto tcp from any to ($ext_if) \
port $tcp_services
pass out on $ext_if proto tcp from any to any port $tcp_services modulate state
Of course this is an extreme example where you ONLY have a web server on port 80 running, but as you can see this
would restrict unauthorized traffic from leaving the internal side of the network. This is more applicable to Host
based firewalls than for router/gateways. This is also pretty tedious to setup and maintain and the calculated gain
is questionable... because if an intruder were to compromise a service on your machine... the chances of
compromising the firewall are rather high as well.
Cute Tricks
IPTables SSH Rate Limit
iptables -A INPUT -m hashlimit -m tcp -p tcp --dport 22 --hashlimit 1/min --hashlimit-mode srcip --hashlimit-name ssh \
-m state --state NEW -j LOG --log-prefix SSHBRUTE
IPTables Forced Replies...
iptables -A LOGREJECT -j LOG --log-level warning --log-prefix 'WEBDROP ' --log-tcp-sequence --log-ip-options --log-tcp-options
iptables -A LOGREJECT -p tcp -j REJECT --reject-with tcp-reset
iptables -A LOGREJECT -j REJECT --reject-with icmp-port-unreachable
Stop NMAP OS Fingerprinting
set-block-policy return
block in log quick proto tcp flags FUP/WEUAPRSF
block in log quick proto tcp flags WEUAPRSF/WEUAPRSF
block in log quick proto tcp flags SRAFU/WEUAPRSF
block in log quick proto tcp flags /WEUAPRSF
block in log quick proto tcp flags SR/SR
block in log quick proto tcp flags SF/SF
(S)YN: synchronize sequence numbers.
(A)CK: acknowledge.
(R)ST: reset.
(F)IN: Finish.
(P)USH: push.
(U)RG: urgent pointer.
(E)CE: (ECN-Echo) explicit congestion notification echo.
C(W)R: congestion window reduced.
More NMAP Spoilers
This messes up the Stealth FIN/Xmas Tree and Null scan modes... it doesn't totally screw it up, but reduces
the accuracy of identifying filtered ports versus open/closed invisible ports.
block in log quick on $Ext inet proto tcp from any to any flags FUP/FUP
block in log quick on $Ext inet proto tcp from any to any flags SF/SFRA
block in log quick on $Ext inet proto tcp from any to any flags /SFRA
block in log quick on $Ext proto tcp from any to any flags SAFRPU
block in log quick on $Ext proto tcp from any to any flags SAFRU/SAFRU
PFTop
pfTop: Up State 1-22/402, View: default, Order: none
PR DIR SRC DEST STATE AGE EXP PKTS BYTES
tcp Out 10.13.13.14:48954 205.188.8.8:5190 4:4 2644m 17995 58683 6745K
tcp Out 10.13.13.14:59986 130.207.107.12:993 4:4 2633m 17968 23489 1878K
tcp In 10.13.13.14:41810 10.13.13.1:22 4:4 235 18000 806 180K
tcp In 10.13.13.14:48954 205.188.8.8:5190 4:4 2644m 17995 58683 6745K
tcp In 10.13.13.14:59986 130.207.107.12:993 4:4 2633m 17968 23489 1878K
tcp In 10.13.13.14:58124 130.207.165.106:993 4:4 26010 17788 461 41381
tcp In 10.13.13.14:58423 130.207.244.116:119 4:4 919 17084 22 2727
tcp In 10.13.13.14:58424 130.207.244.116:119 4:4 918 17083 16 1334
tcp In 10.13.13.14:39423 64.12.160.141:5190 4:4 2644m 17832 1074 43890
tcp In 10.13.13.14:52852 205.188.9.168:5190 4:4 2644m 17972 5702 287K
tcp In 10.13.13.14:43451 216.155.193.174:5050 4:4 2143m 17948 4355 266K
tcp In 10.13.13.14:33034 12.168.116.239:993 4:4 2643m 17789 15329 7166K
tcp In 10.13.13.14:33035 12.168.116.239:993 4:4 2643m 17789 11691 2368K
tcp In 10.13.13.14:33036 12.168.116.239:993 4:4 2643m 17789 8984 1322K
tcp In 10.13.13.14:33037 12.168.116.239:993 4:4 2643m 17789 7238 744K
tcp In 10.13.13.14:33038 12.168.116.239:993 4:4 2643m 17789 6981 691K
tcp In 10.13.13.14:34200 12.168.116.239:22 4:4 213 17936 1059 151K
tcp Out 10.13.13.14:58124 130.207.165.106:993 4:4 26010 17788 461 41381
tcp Out 10.13.13.14:58424 130.207.244.116:119 4:4 918 17083 16 1334
tcp Out 10.13.13.14:58423 130.207.244.116:119 4:4 919 17084 22 2727
tcp Out 10.13.13.14:39423 64.12.160.141:5190 4:4 2644m 17832 1074 43890
tcp Out 10.13.13.14:52852 205.188.9.168:5190 4:4 2644m 17972 5702 287K
Pedantic Security Stuff
ChiliSpot http://www.chillispot.org/
AuthPf http://www.openbsd.org/faq/pf/authpf.html
Yep... thats it...