Thursday, November 14, 2013

JNCIA Lesson 4 1/2 -- More on Routing Policies and Firewall Filtering

One of the concepts that I have struggled with the most while trying to learn JunOS is the filtering language used on Juniper devices. That's a pretty significant problem too, because the filtering language is basically a core feature of JunOS, cropping up in Class of Service/Quality of Service, routing policies, and, of course, basic firewall/security on JunOS devices. It's pretty safe to say that if you don't understand this core concept, you will not be proficient in JunOS, and therefore, I decided I needed to spend a little while playing with the filtering syntax so I can understand it better. In it's most basic form, the filtering rules follow the pattern, "match-action" -- that is, you define a pattern to match, then upon a match, you perform some action on incoming packets -- and then you apply the filter to an interface or VLAN. There are three important concepts to keep in mind when trying to compose a filter rule:
  1. Within a single term, match rules are logical-AND'ed together. That is, if you put a rule to match a source IP address inside a term, then put a second rule to match a destination port, the filter will only match packets from that particular source IP address AND to that particular destination port (i.e., from 192.168.1.17, to port 23). If you want to logically OR rules, you have to create separate terms in the firewall rule-set;
  2. Packets are compared to each term from the top down, and the firewall stops comparing the packet to the firewall rules when it finds a match. In other words, if you put an "allow any" rule as the first term in your match rules, then put specific "deny ..." rules below, all packets will match against the "allow any" and no packet will ever be compared against the "deny ..." rules;
  3. There is an implicit "deny all" at the very end of the firewall rules, even though it is not shown in the configuration. Therefore, you must always make sure that you include rules to match all of the traffic that you want to allow. For example, suppose you are seeing brute-force password guessing attacks through SSH from the IP address 1.2.3.4, so you create a rule to drop traffic matching the source address of 1.2.3.4 and destination port 22. Unless you configure a rule to allow everything else, the implicit "deny all" rule will drop all traffic coming in on the interface or VLAN to which you applied the firewall rule.


Let's start with a simple example: suppose I have a switch on the 192.168.1.0/24 network, I have a host at 192.168.1.1, and on my switch, I want to block ICMP messages from that host with an "ICMP Administratively Prohibited" notification, while allowing any other protocol from 192.168.1.1 or all traffic from other source addresses.

root@branch-3200# set firewall family inet filter no-icmp term drop-icmp from source-address 192.168.1.1

[edit]
root@branch-3200# set firewall family inet filter no-icmp term drop-icmp from protocol icmp

[edit]
root@branch-3200# set firewall family inet filter no-icmp term drop-icmp then reject administratively-prohibited

[edit]
root@branch-3200# commit
commit complete

[edit]
root@branch-3200#


If we attempt to ping 192.168.1.2 (the EX3200 switch) from 192.168.1.1 at this point, we will find the firewall isn't particularly effective:

root@main3200> ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=3.630 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=2.408 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=2.395 ms
^C
--- 192.168.1.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 2.395/2.811/3.630/0.579 ms

root@main3200>


Since we haven't applied the firewall to an interface or VLAN yet, no incoming packets are being compared against the firewall rules, and therefore all inbound traffic is still allowed. Let's take care of that, now:

root@branch-3200# set interfaces vlan unit 0 family inet filter input no-icmp

[edit]
root@branch-3200# commit
commit complete

[edit]
root@branch-3200#


To create our firewall, we started by adding a rule that drops traffic only if the source address is 192.168.1.1. However, we only want to drop ICMP traffic, so we then added a second rule (with the same term name, namely "drop-icmp") that drops ICMP traffic. Since the terms are cumulative, we've essentially created a rule that says, "if the source address matches 192.168.1.1 AND the protocol is ICMP..." Then, we created an action to reject matching packets with the "administratively prohibited" message. Let's see how it works:

root@main3200> ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 d4e0   0 0000  40  01 2275 192.168.1.1  192.168.1.2
<...snip...>
^C
--- 192.168.1.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
root@main3200>


Good, good...

root@main3200> telnet 192.168.1.2
Trying 192.168.1.2...
telnet: connect to address 192.168.1.2: Operation timed out
telnet: Unable to connect to remote host

root@main3200>


Hrmmm...Well, we're half-way there. We are successfully blocking ICMP, but apparently, we are also blocking telnet. Remember, JunOS adds an implicit "deny all" at the end of the firewall rules. Since we create a rule to block ICMP from 192.168.1.1, but we didn't include a rule to allow any packets, we are actually blocking ALL packets on vlan.0. To fix this, we have to add a new term to allow anything that isn't ICMP and from 192.168.1.1:

root@branch-3200# set firewall family inet filter no-icmp term everything-else source 0.0.0.0/0

[edit]
root@branch-3200# set firewall family inet filter no-icmp term everything-else then accept

[edit]
root@branch-3200# commit
commit complete

[edit]
root@branch-3200#


Let's see if that solves the problem:

root@main3200> ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 2f4c   0 0000  40  01 c809 192.168.1.1  192.168.1.2

36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 2f76   0 0000  40  01 c7df 192.168.1.1  192.168.1.2

36 bytes from 192.168.1.2: Communication prohibited by filter
Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
4  5  00 0054 2f9c   0 0000  40  01 c7b9 192.168.1.1  192.168.1.2

^C
--- 192.168.1.2 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

root@main3200> telnet 192.168.1.2
Trying 192.168.1.2...
Connected to 192.168.1.2.
Escape character is '^]'.

branch-3200 (ttyp0)

login:
telnet> quit
Connection closed.

root@main3200>


That's more better :) We are now successfully blocking ICMP from 192.168.1.1 while still allowing other protocols, such as TCP/23 (telnet) to the switch.

However, looking at the firewall rules, something doesn't seem to be right. We have two rules to block source-address 192.168.1.1 and protocol ICMP, but the allow rule only specifies a source-address. How does this rule work?

Keep in mind that JunOS firewall rules work from top down, and they stop looking for matches as soon as a packet matches a term. Consequently, any packet originating from 192.168.1.1 and using the ICMP protocol matches our "reject ..." rule. However, if the packet comes from another source address or is a protocol other than ICMP, JunOS continues comparing the packet with the firewall rules. Therefore, anything not matching the "drop-icmp" term is compared to the "everything-else" term. The "everything-else" term tries to match the packet against the source-address of 0.0.0.0/0 -- in other words, against all possible source IP addresses. Since this second term will match a packet coming from any IP address, it is essentially an "allow any" rule. Therefore, our rule effectively reads, "if the packet matches 192.168.1.1 and matches the ICMP protocol, then reject it with the 'administratively-prohibited' message. If it is anything else, allow it."

No comments:

Post a Comment