7.Cisco ASA Hairpin Internal Server



The Cisco ASA firewall doesn’t like traffic that enters and exits the same interface. This kind of traffic pattern is called hairpinning or u-turn traffic. In the first hairpin example I explained how traffic from remote VPN users was dropped when you are not using split horizon, this time we will look at another scenario.

Take a look at the following topology:

Cisco ASA Hairpin Internal Server

Above we have a webserver using IP address 192.168.1.2 on our internal LAN. The ASA is configured so that IP address 192.168.2.220 on the outside is translated to IP address 192.168.1.2. This allows users on the Internet to access our webserver.




What if we want our internal hosts to access the webserver using the same outside IP address (192.168.2.220) instead of its internal IP address (192.168.1.2)? We can do this by configuring hairpinning on our ASA. Take a look below:


Cisco ASA hairpin internal host

H1 is on the same subnet as the webserver but is trying to reach the webserver using IP address 192.168.2.220. With the default configuration of our ASA, traffic will be routed to the outside and will never end up at the webserver.

Instead of configuring hairpinning it might be a better idea to setup a local DNS server that resolves the hostname of the webserver to the local IP address.
hostname H1
!
interface GigabitEthernet0/1
 ip address 192.168.1.1 255.255.255.0
!
ip default-gateway 192.168.1.254
!
end
hostname Web
!
interface GigabitEthernet0/1
 ip address 192.168.1.2 255.255.255.0
!
ip default-gateway 192.168.1.254
!
end
hostname H2
!
interface GigabitEthernet0/1
 ip address 192.168.2.3 255.255.255.0
!
ip default-gateway 192.168.2.254
!
end
hostname ASA1
!
interface GigabitEthernet0/0
 nameif OUTSIDE
 security-level 0
 ip address 192.168.2.254 255.255.255.0 
!             
interface GigabitEthernet0/1
 nameif INSIDE
 security-level 100
 ip address 192.168.1.254 255.255.255.0 
!
object network WEB_SERVER
 host 192.168.1.2
access-list OUTSIDE_TO_INSIDE extended permit tcp any host 192.168.1.2 
!
object network WEB_SERVER
 nat (INSIDE,OUTSIDE) static 192.168.2.220
access-group OUTSIDE_TO_INSIDE in interface OUTSIDE
!
: end

Let’s see how the ASA is configured at the moment:

ASA1# show xlate 
1 in use, 1 most used
Flags: D - DNS, e - extended, I - identity, i - dynamic, r - portmap,
       s - static, T - twice, N - net-to-net
NAT from INSIDE:192.168.1.2 to OUTSIDE:192.168.2.220
    flags s idle 0:01:37 timeout 0:00:00

Above you can see that the ASA is currently only translating IP address 192.168.1.2 on the inside to IP address 192.168.2.220 on the outside. This allows a host on the outside to reach the webserver:

H2#
H2#telnet 192.168.2.220 80
Trying 192.168.2.220, 80 ... Open

H1 on the inside however is unable to reach the webserver using the outside IP address:

H1#telnet 192.168.2.220 80
Trying 192.168.2.220, 80 ... 
% Connection timed out; remote host not responding

Let’s fix this!

1.Configuration

The first thing we have to do is to tell our ASA to permit traffic that enters and exits the same interface:

ASA1(config)# same-security-traffic permit intra-interface

Now we can focus on the NAT configuration. First I will create some objects that match:

  • the subnet of the internal hosts (192.168.1.0 /24).
  • the translated outside IP address of the webserver.
  • the inside IP address of the webserver.
  • the TCP port that we use for HTTP traffic.

Here are the objects:

ASA1(config)# object-group network INTERNAL_HOSTS
ASA1(config-network-object-group)# network-object 192.168.1.0 255.255.255.0
ASA1(config)# object network WEB_PUBLIC
ASA1(config-network-object)# host 192.168.2.220
ASA1(config)# object network WEB_LOCAL
ASA1(config-network-object)# host 192.168.1.2
ASA1(config# object service HTTP
ASA1(config-service-object)# service tcp destination eq 80

Now we can configure the NAT translation:

ASA1(config-service-object)# nat (INSIDE,INSIDE) source dynamic INTERNAL_HOSTS interface destination static WEB_PUBLIC WEB_LOCAL service HTTP HTTP

The NAT command above requires some explanation:

  • (INSIDE,INSIDE): we are translating traffic from the inside that is going to the inside, this is the hairpinning part.
  • source dynamic INTERNAL_HOSTS interface:  the source of the traffic has to be the 192.168.1.0 /24 subnet and it has to be translated to the IP address of the interface, this will be 192.168.1.254 (the IP address on the inside interface of the ASA).
  • destination static WEB_PUBLIC WEB_LOCAL: we only want to translate traffic that is destined to 192.168.2.220.
  • service HTTP HTTP: we only want to translate traffic that is destined for TCP port 80.

This is everything we need.

You might be wondering why we need to translate the source IP address to the inside IP address of the ASA. If we don’t translate the source IP address of the internal host then we will have asymmetric routing. The webserver will send return traffic directly to the host, it won’t go through the ASA.  We need our return traffic to go through the ASA so we can untranslate it.

2.Verification

Let’s find out if our internal host can now reach the webserver on the outside IP address:

H1#telnet 192.168.2.220 80
Trying 192.168.2.220, 80 ... Open

Great, this seems to be working. Let’s check the ASA:

ASA1# show xlate 
4 in use, 5 most used
Flags: D - DNS, e - extended, I - identity, i - dynamic, r - portmap,
       s - static, T - twice, N - net-to-net
NAT from INSIDE:192.168.1.2 to OUTSIDE:192.168.2.220
    flags s idle 0:04:17 timeout 0:00:00
TCP PAT from INSIDE:192.168.1.2 80-80 to INSIDE:192.168.2.220 80-80
    flags srT idle 0:00:15 timeout 0:00:00

TCP PAT from INSIDE:192.168.1.1/45675 to INSIDE:192.168.1.254/45675 flags ri idle 0:00:15 timeout 0:00:30

Above you can see that 192.168.1.1 has been translated to 192.168.1.254.

hostname H1
!
interface GigabitEthernet0/1
 ip address 192.168.1.1 255.255.255.0
!
ip default-gateway 192.168.1.254
!
end
hostname Web
!
interface GigabitEthernet0/1
 ip address 192.168.1.2 255.255.255.0
!
ip default-gateway 192.168.1.254
!
end
hostname H2
!
interface GigabitEthernet0/1
 ip address 192.168.2.3 255.255.255.0
!
ip default-gateway 192.168.2.254
!
end
hostname ASA1
!
interface GigabitEthernet0/0
 nameif OUTSIDE
 security-level 0
 ip address 192.168.2.254 255.255.255.0 
!             
interface GigabitEthernet0/1
 nameif INSIDE
 security-level 100
 ip address 192.168.1.254 255.255.255.0 
!
same-security-traffic permit intra-interface
!
object network WEB_LOCAL
 host 192.168.1.2
!
object network WEB_PUBLIC
 host 192.168.2.220
!
object network INTERNAL_HOSTS
subnet 92.168.1.0 255.255.255.0
!
object service HTTP
 service tcp destination eq www 
!
object network LAN_TO_PUBLIC
 subnet 192.168.1.0 255.255.255.0
!
access-list OUTSIDE_TO_INSIDE extended permit tcp any host 192.168.1.2 
!
nat (INSIDE,INSIDE) source dynamic INTERNAL_HOSTS interface destination static WEB_PUBLIC WEB_LOCAL service HTTP HTTP
!
object network WEB_SERVER
 nat (INSIDE,OUTSIDE) static 192.168.2.220
access-group OUTSIDE_TO_INSIDE in interface OUTSIDE
!
: end

3.Conclusion

When you want your internal hosts to reach an internal server using the outside IP address, you will have to configure hairpinning. Make sure you translate the source and destination addresses otherwise you will end up with asymmetric routing. If you have any questions, feel free to leave a comment.

Comments

Popular posts from this blog

Cisco ASA Packet Drop Troubleshooting

show asp drop Command Usage

1.Cisco ASA Clock Configuration