Oct 6, 2010

Forwarding services through a secondary ISP

In this post I'm going to show how to implement a policy to forward some specific service through a secondary ISP. A dual-ISP scenario was described in my post about redundancy.


The following command lines are required to forward SMTP traffic through the ISP2:

route outside 0.0.0.0 0.0.0.0 192.168.0.254 1
route out-backup 0.0.0.0 0.0.0.0 172.16.0.254 2
nat (inside) 1 0.0.0.0 0.0.0.0
global (outside) 1 interface
global (out-backup) 1 interface
static (out-backup,inside) tcp 0.0.0.0 smtp 0.0.0.0 smtp netmask 0.0.0.0

 
The static statement is a destination NAT (outside NAT) and forces any SMTP traffic to be forwarded through the secondary ISP, even with the default route pointing to the ISP1 gateway. The default route with a higher administrative distance is necessary to route the outbound traffic and for the reverse traffic to be accepted via out-backup. If this route is not implemented, the following error happens:
 
Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: out-backup
output-status: up
output-line-status: up

Action: drop
Drop-reason: (no-adjacency) No valid adjacency

 
I have ran two traffic simulations to demonstrate how the firewall would handle HTTP and SMTP traffic for the same source and destination.

HTTP traffic simulation:
 
asa# packet-tracer input inside tcp 192.168.100.25 80 172.31.0.100 80

Phase: 1
Type: FLOW-LOOKUP
Subtype:
Result: ALLOW
Config:
Additional Information:
Found no matching flow, creating a new flow

Phase: 2
Type: ROUTE-LOOKUP
Subtype: input
Result: ALLOW
Config:
Additional Information:
in   0.0.0.0         0.0.0.0         outside

Phase: 3
Type: ACCESS-LIST
Subtype: log
Result: ALLOW
Config:
access-group inside_access_in in interface inside
access-list inside_access_in extended permit ip any any
Additional Information:

Phase: 4
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 5
Type: NAT
Subtype:
Result: ALLOW
Config:
nat (inside) 1 0.0.0.0 0.0.0.0
  match ip inside any outside any
    dynamic translation to pool 1 (192.168.0.1 [Interface PAT])
    translate_hits = 8, untranslate_hits = 0
Additional Information:
Dynamic translate 192.168.100.25/80 to 192.168.0.1/405 using netmask 255.255.255.255

Phase: 6
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
nat (inside) 1 0.0.0.0 0.0.0.0
  match ip inside any outside any
    dynamic translation to pool 1 (192.168.0.1 [Interface PAT])
    translate_hits = 8, untranslate_hits = 0
Additional Information:

Phase: 7
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 8
Type: FLOW-CREATION
Subtype:
Result: ALLOW
Config:
Additional Information:
New flow created with id 23, packet dispatched to next module

Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: outside
output-status: up
output-line-status: up

Action: allow



SMTP traffic simulation:

asa# packet-tracer input inside tcp 192.168.100.25 25 172.31.0.100 25

Phase: 1
Type: FLOW-LOOKUP
Subtype:
Result: ALLOW
Config:
Additional Information:
Found no matching flow, creating a new flow

Phase: 2
Type: UN-NAT
Subtype: static
Result: ALLOW
Config:
static (out-backup,inside) tcp 0.0.0.0 smtp 0.0.0.0 smtp netmask 0.0.0.0
  match tcp out-backup any eq 25 inside any
    static translation to 0.0.0.0/25
    translate_hits = 0, untranslate_hits = 2
Additional Information:
NAT divert to egress interface out-backup
Untranslate 0.0.0.0/25 to 0.0.0.0/25 using netmask 0.0.0.0

Phase: 3
Type: ACCESS-LIST
Subtype: log
Result: ALLOW
Config:
access-group inside_access_in in interface inside
access-list inside_access_in extended permit ip any any
Additional Information:

Phase: 4
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 5
Type: INSPECT
Subtype: inspect-smtp
Result: ALLOW
Config:
Additional Information:

Phase: 6
Type: NAT
Subtype:
Result: ALLOW
Config:
nat (inside) 1 0.0.0.0 0.0.0.0
  match ip inside any out-backup any
    dynamic translation to pool 1 (172.16.0.1 [Interface PAT])
    translate_hits = 8, untranslate_hits = 0
Additional Information:
Dynamic translate 192.168.100.25/25 to 172.16.0.1/216 using netmask 255.255.255.255

Phase: 7
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
nat (inside) 1 0.0.0.0 0.0.0.0
  match ip inside any outside any
    dynamic translation to pool 1 (192.168.0.1 [Interface PAT])
    translate_hits = 8, untranslate_hits = 0
Additional Information:

Phase: 8
Type: NAT
Subtype: rpf-check
Result: ALLOW
Config:
static (out-backup,inside) tcp 0.0.0.0 smtp 0.0.0.0 smtp netmask 0.0.0.0
  match tcp out-backup any eq 25 inside any
    static translation to 0.0.0.0/25
    translate_hits = 0, untranslate_hits = 2
Additional Information:

Phase: 9
Type: NAT
Subtype: host-limits
Result: ALLOW
Config:
static (out-backup,inside) tcp 0.0.0.0 smtp 0.0.0.0 smtp netmask 0.0.0.0
  match tcp out-backup any eq 25 inside any
    static translation to 0.0.0.0/25
    translate_hits = 0, untranslate_hits = 2
Additional Information:

Phase: 10
Type: IP-OPTIONS
Subtype:
Result: ALLOW
Config:
Additional Information:

Phase: 11
Type: FLOW-CREATION
Subtype:
Result: ALLOW
Config:
Additional Information:
New flow created with id 24, packet dispatched to next module

Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: out-backup
output-status: up
output-line-status: up

Action: allow



asa# show conn
2 in use, 2 most used
TCP out-backup 172.31.0.100:25 inside 192.168.100.25:25, idle 0:00:01, bytes 0, flags saA
TCP outside 172.31.0.100:80 inside 192.168.100.25:80, idle 0:00:04, bytes 0, flags saA



asa(config)# end
asa# wr mem

7 comments:

  1. Amigo,

    Implementei a sua solução em um cliente e funcionou perfeitamente...

    Obrigado por compartilhar seu conhecimento com todos!

    ReplyDelete
  2. Do you know of a way to accept VPN client connections from the secondary ISP while using tracking, and tracking is using the primary ISP?

    Thank you!

    ReplyDelete
  3. @Ian

    Hello Ian,

    You just have to enable isakmp and assign a crypto map to the secondary outside interface. Then you set the VPN client to connect to the secondary ISP IP address. In other words, you have to do everything you'd do on a single ISP scenario but using the secondary outside interface.

    The following posts might be helpful for you:
    Steps to setup a VPN on ASA/PIX
    High availability using ASA/PIX

    ReplyDelete
  4. I have done this but I can only ping the outside IP that the tracking is marking as primary.

    The VPN on the second IP times out unless I check the route metric to be less than the primary.

    Then I can ping and connect the VPN.

    ReplyDelete
  5. @Ian

    Did you add a static route to the IP pool through the secondary outside interface?

    ip local pool client-pool 192.168.1.1-192.168.1.254
    static outside-bkp 192.168.1.0 255.255.255.0

    You can also try to add 'tunneled' keyword to the secondary default route:

    route outside-bkp 0 0 255 tunneled

    ReplyDelete
  6. I have a route for my back up ISP.

    ASA# show run | include ip local pool
    ip local pool vpn_pool 10.1.0.10-10.1.0.20 mask 255.255.255.0

    I am using this pool for both tunnel groups.
    I can see this being a problem for return traffic. I don’t see how this would stop me pinging the backup outside IP or connection the VPN.

    I see a lot of posts on line that the ASA only support one ISP active at a time. Do you know if this is correct?

    ReplyDelete
  7. @Ian

    I will lab this scenario and let you know the results.

    ReplyDelete