For the purposes of penetration testing, add a route on Outside1 so it sends packets to F1 in order to get to the network 10.18.2.0/24.
Test if Outside1 can address internal hosts (it will be able to, although this is undesirable). In this section, we shall aim to prevent this, as well as implement and test the policies defined earlier.
One thing you have to realise about Vyatta firewalls is that as soon as you attach one packet filter to an interface, all interface firewalls change their default behaviour from allow to drop. This means packets will get dropped (silently), which is fine enough on a production firewall, but very frustrating when you are trying to figure out why packets are getting dropped. To help with this, we shall start by defining a simple packet filter for each firewall that implements the stateful rule (to allow packets associated to/with already allowed sessions) and logs and then drops each other packet that it sees. That way, we can add rules to packets filters in a nice piecemeal fashion. The logs will be sufficient for us to know which packet filter we need to adjust, and we simply adjust the packet filters until the policy works.
Internally, Vyatta does it firewalling using IPTables. However, for those with IPTables experience, there is one important difference to beware of. set action accept does not translate to a iptables … -j ACCEPT but rather a iptables … -j RETURN. set action drop however, does translate to a iptables … -j DROP.
The annoying thing about this is that for traffic that goes through the router (ie. the IPTables FORWARD chain) you need to add rules to allow traffic in the relavent “in” and “out” packet filters. The diagrams in the Vyatta Firewall documentation show clearly how packets traverse the firewall.
Each interface has three firewalls, in,
out and local. F1 has three
interfaces, so we will eventually want up to nine packet
filters.
We shall name our packet filters in a logical manner,
following the template
FW_NETWORK_FIREWALL,
so the packet filter attached to the in
firewall on the Fake Internet shall be called
FW_INTERNET_IN.
That’s a lot of tedious typing. For that reason, it is a common technique to generate router configurations, which you can then easily paste into a configuration session over a Serial console or SSH (or, if you really want, Telnet). For this reason, you may prefer to enable SSH on F1 allowing access from Client1, then SSH into F1 from Client1. Here’s how to do that:
$set service ssh protocol-version v2$commit
And now, on Client1 (thats the Client1 in the Firewall lab), connect to F1:
client1$ssh vyatta@10.18.0.1…
On Client1, we shall generate commands to produce our nine initial packet filters by using a shell-script. Each packet filter will start with the stateful rule, and end with a log-and-drop. After testing, you can manually remove the log enable directives. Put the following into a script and run it (or use some suitable “editor wizardry” if you prefer). Then paste the result into a configuration session on Vyatta.
for net in INTERNET DMZ LAN; do
for fw in IN OUT LOCAL; do
echo edit firewall name FW_${net}_${fw} rule 10
echo set description '"Allow already accepted traffic"'
echo set action accept
echo set state established enable
echo set state related enable
echo top
echo edit firewall name FW_${net}_${fw} rule 1024
echo set description '"Log and Drop traffic by default"'
echo set action drop
echo set log enable
echo top
done
doneAfter you paste the output of these commands into your SSH session, remember to commit and save. Don’t you just love automation?
Let’s see the effect of our work. show firewall and see what has been added. However, the packet filter’s aren’t actually doing anything yet, because they are not attached to the interfaces. A lot more commands, although this time, less repetitive.
echo 'eth2 INTERNET
eth1 DMZ
eth0 LAN' | while read iface net
do
for fw in in out local
do
echo set interfaces ethernet $iface firewall $fw name FW_${net}_${fw^^}
done
done
pattern^^}The substitution ${fw^^} simply
uppercases the value of the fw variable. It is
not available in older versions of Bash, such as that which come
with Vyatta. It is available on Ubuntu 10.04 LTS at
least.
Don’t forget to show interfaces, commit and then save.
However, now you might run into your first stumbling block. If you were connected via SSH, you may very well find that you are no-longer able to interact with the router. If you abort the SSH connection (using Return ~ .) and attempt to reconnect, the connection attempt will hang. If, on the F1 console (not via SSH) you do a run show log tail 3 on your firewall, you will find an entry such as the following (we’ve highlighted the more interesting parts):
$run show log tail 3timestampvyatta kernel: [ignorable] [FW_LAN_LOCAL-1024-D] ↩ IN=eth0 OUT= MAC=src-mac:dst-mac:ether-protoSRC=10.18.2.10 DST=10.18.2.1 ↩ LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=78110 DF ↩ PROTO=TCP SPT=52099 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0
Before we proceed, let’s check our understanding of the log message:
This is formed by the packet filter name, the rule name, and the fact that it was logged in a ‘drop’ rule. Thus, we know exactly where in our firewall it was dropped, and which packet filter we need to modify to let it through.
From this we can infer that it is a ‘local’ chain, because it is going into the router, but not out.
In IPTables, this would appear on the ‘INPUT’ primary chain, rather than the ‘FORWARD’ or ‘OUTPUT’ chain.
We can emphatically say that the connection attempt came from the LAN, which is eth0.
The source address tells us the packet appears to have come from Client1, and was sent to the the IP address of F1’s LAN interface. Note that this could be spoofed, although most firewalls will have options turned on to detect spoofed traffic where possible.
This is one of the things we need to know in order to match the traffic: that it is TCP.
Knowing the destination port (in this case it is TCP/22, which is SSH) is also one of the key ways we match different types of traffic.
For TCP, the source port is generally a short-lived, random high-numbered port (we call it an ephemeral port) and as such we generally don’t concern ourselves with the source port. But occassionally we do also consult the source port for some UDP traffic.
For TCP traffic, the SYN bit is set in the header for the first packet, thus this packet is understood to be initiating an SSH connection to F1, from the LAN.
So now we should be able to add a rule that allows us to get past this problem:
$edit firewall name FW_LAN_LOCAL$showrule 10 is the stateful rule… … and rule 1024 is the default drop … … so we want our rule to be perhaps rule 20.$edit rule 20$set description "Allow SSH from Client1 only"$set action accept$set protocol tcp$set state new enable$set destination port ssh$set source address 10.18.2.10Note that we only want one host in the LAN to access F1 via SSH. For other protocols, we would typically specify a prefix, such as 10.18.2.0/25$commit
Now check that you can access F1 via SSH from Client1. Make sure you take note of the timestamp in the logs so you can ignore log messages from previous attempts.
You may find it a lot more convenient if you log into another virtual terminal on F1, and run the command tail -f /var/log/kern.log, which is where the kernel logs are routed to on Vyatta.
The reason that this is more convenient is that you can simple type Return a few times in order to visually separate old messages from new messages.
Now you can go on and implement the rest of the policy, using the same techniques.
When you are finished, you may want to adjust your logging. You don’t want to log everything, as it could be used as an attack vector (either to fill up hard-disk space, or to erase logs that might be stored in a ring-buffer). But you generally want to keep some record of the sorts of things you are dropping.
Testing-by-doing is the easiest way of checking if the system works, but it is not the only method you should use to audit your firewall. In particular, you should “desk-check” the configuration to see if you are missing anything, particularly to check that you haven’t left out a default case. In a real-world situation you would also test the firewall rules with tools such as port-scanners (eg. nmap) and packet injection tools, but the latter is rather more advanced that this lab should go and the tools are not available in the default Ubuntu Live CD (although there are Live CDs that do, you might like to look around).