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:

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:

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.
- Startup Configurations
- H1
- Web
- H2
- ASA1
hostname H1
!
interface GigabitEthernet0/1
ip address 192.168.1.1 255.255.255.0
!
ip default-gateway 192.168.1.254
!
endhostname Web
!
interface GigabitEthernet0/1
ip address 192.168.1.2 255.255.255.0
!
ip default-gateway 192.168.1.254
!
endhostname H2
!
interface GigabitEthernet0/1
ip address 192.168.2.3 255.255.255.0
!
ip default-gateway 192.168.2.254
!
endhostname 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
!
: endLet’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:00Above 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 ... OpenH1 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 respondingLet’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-interfaceNow 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.0ASA1(config)# object network WEB_PUBLIC
ASA1(config-network-object)# host 192.168.2.220ASA1(config)# object network WEB_LOCAL
ASA1(config-network-object)# host 192.168.1.2ASA1(config# object service HTTP
ASA1(config-service-object)# service tcp destination eq 80Now 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 HTTPThe 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.
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 ... OpenGreat, 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:30Above you can see that 192.168.1.1 has been translated to 192.168.1.254.
- Final Configurations
- H1
- Web
- H2
- ASA1
hostname H1
!
interface GigabitEthernet0/1
ip address 192.168.1.1 255.255.255.0
!
ip default-gateway 192.168.1.254
!
endhostname Web
!
interface GigabitEthernet0/1
ip address 192.168.1.2 255.255.255.0
!
ip default-gateway 192.168.1.254
!
endhostname H2
!
interface GigabitEthernet0/1
ip address 192.168.2.3 255.255.255.0
!
ip default-gateway 192.168.2.254
!
endhostname 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
!
: end3.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
Post a Comment