juniper

Juniper SRX: filter-based forwarding based on source-ip

In a poor mans multi-homing setup, you'll have a firewall with two ISP connections. Each connection has its own IP space. This makes load-balancing a bit tricky. You can't just do per-session load balancing because that causes the clients public IP address to change at random. For some applications, that is not a problem, but there are many that lock a user to a specific IP. A common example are banking websites, as soon as the IP address changes, the user session is terminated.
An easy workaround would be to disable load-balancing for HTTP and HTTPS sessions, but nowadays that's most of the traffic.

In searching for a solution to this problem, I thought of a very easy workaround: load-balancing based on the clients (internal) IP address. This ensures that the same client always uses the same ISP connection, so the public IP address remains the same. Assuming a random distribution of the internal IP addresses, this should provide an even distribution of sessions between the two ISPs.

As it turns out, this can be done in JunOS quite easily. All it takes is a special use of subnet masks. Assuming you have two routing-instances, one for each ISP, the following firewall filter applied on the client-facing interface will distribute the traffic across the two connections. All clients whose IP address ends in an even number, are routed via ISP1 and clients whose IP address ends in an uneven number, are sent via ISP2.

  1. firewall {
  2. family inet {
  3. filter source-based-lb {
  4. term even {
  5. from {
  6. source-address {
  7. 10.32.0.0/255.255.0.1;
  8. }
  9. }
  10. then {
  11. routing-instance fbf-prefer-isp1;
  12. }
  13. }
  14. term odd {
  15. from {
  16. source-address {
  17. 10.32.0.1/255.255.0.1;
  18. }
  19. }
  20. then {
  21. routing-instance fbf-prefer-isp2;
  22. }
  23. }
  24. term default {
  25. then accept;
  26. }
  27. }
  28. }
  29. }

Of course, replace 10.32. with the users IP range. I tried using 0.0.0.0/0.0.0.1 and 0.0.0.1/0.0.0.1 in the firewall filter but that seems to trigger a bug in the junos CLI.

Using Time Domain Reflectometry (TDR) to locate cable faults on EX switches

One of the little known features of the Juniper EX switches is Time domain reflectometry which can be used to locate cable faults.
This is especially useful for long cables or when a connection is made up of multiple patch cables, to figure out where the cable is damaged.

To start TDR on a port, issue the following command:

  1. request diagnostics tdr start interface <interface>

The test will take a couple seconds. To see the results, use:
  1. show diagnostics tdr interface <interface>

On a working link, the result looks something like this:

  1. Interface TDR detail:
  2. Interface name : ge-1/0/26
  3. Test status : Passed
  4. Link status : UP
  5. MDI pair : 1-2
  6. Cable status : Normal
  7. Distance fault : 0 Meters
  8. Polartiy swap : Normal
  9. Skew time : 0 ns
  10. MDI pair : 3-6
  11. Cable status : Normal
  12. Distance fault : 0 Meters
  13. Polartiy swap : Normal
  14. Skew time : 0 ns
  15. MDI pair : 4-5
  16. Cable status : Normal
  17. Distance fault : 0 Meters
  18. Polartiy swap : Normal
  19. Skew time : 8 ns
  20. MDI pair : 7-8
  21. Cable status : Normal
  22. Distance fault : 0 Meters
  23. Polartiy swap : Normal
  24. Skew time : 0 ns
  25. Channel pair : 1
  26. Pair swap : MDIX
  27. Channel pair : 2
  28. Pair swap : MDIX
  29. Downshift : No Downshift

When something is wrong with the cable, the results may vary of course. A cable which simply isn't connected to anything at the far end shows up like this:

  1. Interface TDR detail:
  2. Interface name : ge-1/0/16
  3. Test status : Passed
  4. Link status : Down
  5. MDI pair : 1-2
  6. Cable status : Open
  7. Distance fault : 52 Meters
  8. Polartiy swap : N/A
  9. Skew time : N/A
  10. MDI pair : 3-6
  11. Cable status : Open
  12. Distance fault : 50 Meters
  13. Polartiy swap : N/A
  14. Skew time : N/A
  15. MDI pair : 4-5
  16. Cable status : Open
  17. Distance fault : 50 Meters
  18. Polartiy swap : N/A
  19. Skew time : N/A
  20. MDI pair : 7-8
  21. Cable status : Open
  22. Distance fault : 52 Meters
  23. Polartiy swap : N/A
  24. Skew time : N/A
  25. Channel pair : 1
  26. Pair swap : N/A
  27. Channel pair : 2
  28. Pair swap : N/A
  29. Downshift : N/A

Configuring an IPv6 tunnel on Juniper SRX

After using my old netscreen 5GT for years to terminate my IPv6 tunnel, I replaced it with an SRX100. IPv6 support on the SRX is still fairly new compared to the netscreen but so far I haven't had any problems with it and some of the limitations that existed in netscreen have been removed as well. Netscreen is stable as a rock, but SRX is a lot more fun :)

My goal was to configure an IPv6 tunnel on my SRX and performing stateful firewalling. I mention stateful firewalling explicitly because the SRX can be configured in either packet-mode or flow-mode. In packet mode it will simply route the IPv6 packets but bypass the security module, in flow-mode it will send everything through the security module as well. Packet-mode is useful for routers, but my SRX is running as a firewall, so I need flow-mode.

The first step is to decide which Junos version to run. This is a bit of a challenge because IPv6 tunnel support in flow-mode worked in some versions but not others. To my knowledge support looks a bit like this:

< 10.2 No ipv6 flow-mode support
10.2 ipv6 flow-mode support, not tunneled, no RVI interfaces
10.3 working ipv6 flow-mode with tunnel, no RVI interfaces
10.4 ipv6 flow-mode support, not tunneled, no RVI interfaces
11.1R2 working ipv6 flow-mode with tunnel and RVI interfaces

Quite a challenge. See this thread on the juniper forums for more details. It also contains a workaround for 10.4. I like testing out new features, so my setup is running 11.1R2. If you are running one of these older versions, you might want to try out packet-mode first (which has been working for ages) and once that works, switch to flow-mode.

Example network

As an example, I'll set up a tunnel to a tunnel broker with the following settings:

  • Tunnel broker ipv4 address: 127.34.8.97
  • My public ipv4 address: 127.78.134.3
  • Tunnel ipv6 address: 2001:db8:202:123::2/64
  • Internal ipv6 subnet: 2001:db8:8aa:1::/64

Note that I'm using a fixed IPv4 address on my firewall here, which is required by the SRX configuration. I don't really have a fixed IP, but I'm using a small event script which alters my configuration each time my external IP changes. I'll include that below. That's the power of Junos, you can automate a lot. More on that later.

Tunnel setup

Creating the tunnel is as easy as creating a new IP tunnel interface and adding it to a security zone.

  1. [edit interfaces ip-0/0/0]
  2. unit 0 {
  3. tunnel {
  4. source 127.78.134.3;
  5. destination 127.34.8.97;
  6. }
  7. family inet6 {
  8. mtu 1280;
  9. address 2001:db8:202:123::2/64;
  10. }
  11. }
  12. [edit security zones security-zone untrust]
  13. interfaces {
  14. ip-0/0/0.0 {
  15. host-inbound-traffic {
  16. system-services {
  17. ping;
  18. }
  19. }
  20. }
  21. }

That's it, now you should be able to ping IPv6 addresses from the SRX itself.

Internal networks

To assign addresses to internal machines, SLAAC is used. The SRX sends out router-advertisements containing the prefix assigned to the network and clients will chose an address from that range. DHCPv6 could be used as an alternative, but that's a topic for a future blog.

  1. [edit configuration protocols router-advertisement]
  2. interface fe-0/0/1.0 {
  3. prefix 2001:db8:8aa:1::/64 {
  4. on-link;
  5. autonomous;
  6. }
  7. }
  8. [edit configuration interfaces fe-0/0/1]
  9. unit 0 {
  10. family inet6 {
  11. address 2001:db8:8aa:1::/64;
  12. }
  13. }
  14. [edit security zones security-zone trust]
  15. interfaces {
  16. fe-0/0/1;
  17. }

At this point, internal machines should be assigned an IPv6 address and should be able to ping the SRX.

Security Policy

Configuring security policies can be done just like IPv4 policies. Unlike netscreen, you can even combine IPv4 and IPv6 addresses in policies. So the following default policy will allow full internet access to you're internal machines on both IPv4 and IPv6:

  1. [edit security policies from-zone trust to-zone untrust]
  2. policy trust-to-untrust {
  3. match {
  4. source-address any;
  5. destination-address any;
  6. application any;
  7. }
  8. then {
  9. permit;
  10. }
  11. }

Terminating the tunnel on a dynamic IP

To terminate the IPv6 tunnel on a dynamic IP address, first you'll need to run some utility on an internal machine to update the tunnel broker side of the tunnel. This is specific to whichever service you are using.

As you can see in the config above, you need to specify your public IP address in the SRX tunnel setup. Each time that address changes, you would have to re-configure the SRX. That is a lot of work but this can be done automatically by running an event script on the SRX. This script will run each time the address of the interface changes and will update the config accordingly.

The script (ipv6-tunnel-update.slax) is attached to this article, it's not pretty but it works. Before copying this to the SRX, edit it and replace "fe-0/0/0.0" with the name of your uplink interface.
To activate the script, copy it to /var/db/scripts/event on the SRX and add the following to the config:

  1. [edit configuration event-options]
  2. policy ipv6-tunnel-endpoint-update {
  3. events SYSTEM;
  4. attributes-match {
  5. SYSTEM.message matches "EVENT Add";
  6. }
  7. then {
  8. event-script ipv6-tunnel-update.slax;
  9. }
  10. }
  11. event-script {
  12. file ipv6-tunnel-update.slax;
  13. }

The script was based on this one but altered to support non-PPP interfaces. I would love to see the automation guru's write a more generic version.

Blog Category:

Creating a global firewall policy on Juniper SRX

Juniper firewalls, both netscreen and SRX, use a concept of security zones. Each interface is assigned to a zone and firewall policies are created between zones to permit traffic. This is very useful as you can safely use the "Any" object in firewall rules without unexpected results. However, sometimes its useful to create policies regardless of the source and destination zones. The most common reason is to create a default deny rule with logging enabled.

On netscreen firewalls, there was a global rulebase which was evaluated if there was no matching rule in the regular rulebase. On SRX series however, there is no global rulebase. So in order to create default deny rules with logging enabled, you have to create rules for each possible combination of source and destination zone. This can be a lot of work as the number of policies required increases exponentially.

Tired of creating so many rules, I figured there had to be an easier way. This device is running JUNOS, there must be some feature or script that can help simplify this, and there is. Its a feature called configuration groups which makes it easy to repeat a piece of configuration multiple times. This following example create a firewall rule that drops and logs all traffic. This rule is then appended to each rule set:

  1. set groups global-policy security policies from-zone <*> to-zone <*> policy default-logdrop match source-address any
  2. set groups global-policy security policies from-zone <*> to-zone <*> policy default-logdrop match destination-address any
  3. set groups global-policy security policies from-zone <*> to-zone <*> policy default-logdrop match application any
  4. set groups global-policy security policies from-zone <*> to-zone <*> policy default-logdrop then deny
  5. set groups global-policy security policies from-zone <*> to-zone <*> policy default-logdrop then log session-init
  6.  
  7. set security policies apply-groups global-policy

This can easily be extended to create address objects in multiple zones at once, or modified to apply only to select rule sets.

The apply-group is not entirely the same as the global policy on netscreen, it will only create a default log+drop rule in each existing rule set. So if there are two zones for which no policy exists yet, no drop rule will be installed either.

Pages

Subscribe to RSS - juniper