What is hair-pinning?
Hair-pinning is when ASA appliance is receiving traffic on an interface and immediately sending traffic back out the same interface.
This feature could be enabled by using the following command:
ASA(config)# same-security-traffic permit intra-interface
Encrypted traffic can be redirected through same interface as encrypted and as a clear traffic - feature from ASA software version 7.2(1). Hair-pinning is useful for many different scenarios.
Let's consider following scenario.
R1 which is our test host is connected to ASA inside interface and same ASA interface is attached to R2. I know, looks a bit weird, but this is just simple scenario for the feature test.
ASA has route for network 172.16.2.0 over the router R2 (172.16.1.100)
ASA(config)# route inside 172.16.2.0 255.255.255.0 172.16.1.100
R1 has ASA 172.16.1.1 inside interface configured as default gateway.
Basic connectivity check:
ASA# ping 172.16.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 10/24/30 ms
ASA#
test_host#ping 172.16.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.2.2, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)
test_host#
To make this working, hair-pinning has to be enabled. Before enabling the feature, I would like to check few more things. What about telnet from R2 and R1 (test_host) to R3 interface 172.16.2.2.
R2#telnet 172.16.2.2
Trying 172.16.2.2 ... Open
Password required, but none set
[Connection to 172.16.2.2 closed by foreign host]
Perfect, everything is working like expected (R2 is able to establish connectivity, R1 is not).
Packet tracer from ASA:
ASA# packet-tracer input inside tcp 172.16.2.200 6666 172.16.2.2 telnet detailed
...
Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: inside
output-status: up
output-line-status: up
Action: drop
Drop-reason: (acl-drop) Flow is denied by configured rule
Obviosuly, packet is not reaching R3 (I would like to see what is happening from R3 perspective with debug ip packet command). Same test again:
R3#debug ip packet
IP packet debugging is on
R3#
test_host#telnet 172.16.2.2
Trying 172.16.2.2 ...
R3#debug ip packet
IP packet debugging is on
R3#
Hmm, nothing. Let's allow hair-pinning on ASA itself:
ASA(config)# same-security-traffic permit intra-interface
icmp test from R1:
test_host#ping 172.16.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 28/42/60 ms
test_host#
telnet attempt is reaching R3 (just reaching, session is not established):
test_host#telnet 172.16.2.2
Trying 172.16.2.2 ...
Packets are indeed reaching R3:
R3#
*Mar 1 00:53:55.463: IP: tableid=0, s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), routed via RIB
*Mar 1 00:53:55.463: IP: s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), len 44, rcvd 3
*Mar 1 00:53:55.471: IP: tableid=0, s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), routed via FIB
*Mar 1 00:53:55.471: IP: s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), len 44, sending
*Mar 1 00:53:55.551: IP: tableid=0, s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), routed via RIB
*Mar 1 00:53:55.551: IP: s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), len 40, rcvd 3
R3#
*Mar 1 00:53:57.459: IP: tableid=0, s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), routed via RIB
*Mar 1 00:53:57.463: IP: s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), len 44, rcvd 3
*Mar 1 00:53:57.463: IP: tableid=0, s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), routed via FIB
*Mar 1 00:53:57.467: IP: s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), len 40, sending
*Mar 1 00:53:57.475: IP: tableid=0, s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), routed via FIB
*Mar 1 00:53:57.475: IP: s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), len 44, sending
Packet tracer from ASA:
ASA(config)# packet-tracer input inside tcp 172.16.2.200 6666 172.16.2.2 telnet detailed
...
Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: inside
output-status: up
output-line-status: up
Action: allow
So, perfect! Did I say everything is fine? Well, yes and no.... My telnet is getting to R3 but connectivity is not fully working. Why? Whireshark will help us to get answer on this question.
I am running Wireshark on router R3 interface where R2 is attached:
Three-way handshake is not fully passing ASA appliance.
R1 (172.16.1.200) is sending SYN packet
R3 (172.16.2.2) is sending back SYN/ACK
R1 (172.16.1.200) is sending RST
Looks like SYN/ACK is not passing ASA, instead it is leaving switch and going straight to R1. We do have asymmetric scenario. Solution is TCP State Bypass feature.
According to the Cisco, TCP State Bypas requires following steps:
1. Use the class-map class_map_name command in order to create a class map. The class map is used to identify the traffic for which you want to disable stateful firewall inspection. The class map used in this example is tcp_bypass.
ASA(config)#class-map tcp_bypass
2. Use the match parameter command in order to specify interesting traffic in the class map. When using the Modular Policy Framework, use the match access-list command in class-map configuration mode in order to use an access list to identify traffic to which you want to apply actions. Here is an example of this configuration:
ASA(config)#class-map tcp_bypass
ASA(config-cmap)#match access-list tcp_bypass
tcp_bypass is the name of the access-list used in this example. Refer to Identifying Traffic (Layer 3/4 Class Map) for more information on specifying the interesting traffic.
3. Use the policy-map name command in order to add a policy map or edit a policy map (which is already present) that sets the actions to take with the class map traffic specified already. When using the Modular Policy Framework, use the policy-map command (without the type keyword) in global configuration mode in order to assign actions to traffic that you identified with a Layer 3/4 class map (the class-map or class-map type management command). In this example, the policy map is tcp_bypass_policy:
ASA(config-cmap)#policy-map tcp_bypass_policy
4. Use the class command in policy-map configuration mode in order to assign the class map (tcp_bypass) already created to the policy map (tcp_bypass_policy) where you can assign actions to the class map traffic . In this example, the class map is tcp_bypass:
ASA(config-cmap)#policy-map tcp_bypass_policy
ASA(config-pmap)#class tcp_bypass
5. Use the set connection advanced-options tcp-state-bypass command in class configuration mode in order to enable the TCP state bypass feature. This command was introduced in version 8.2(1). The class configuration mode is accessible from the policy-map configuration mode as shown in this example:
ASA(config-cmap)#policy-map tcp_bypass_policy
ASA(config-pmap)#class tcp_bypass
ASA(config-pmap-c)#set connection advanced-options tcp-state-bypass
6.Use the service-policy policymap_name [ global | interface intf ] command in global configuration mode in order to activate a policy map globally on all interfaces or on a targeted interface. In order to disable the service policy, use the no form of this command. Use the service-policy command to enable a set of policies on an interface.global applies the policy map to all interfaces, and interface applies the policy to one interface. Only one global policy is allowed. You can override the global policy on an interface by applying a service policy to that interface. You can apply only one policy map to each interface.
ASA(config-pmap-c)#service-policy tcp_bypass_policy outside
Our configuration example is:
ASA(config)# access-list tcp_bypass_range extended permit tcp 172.16.1.0 255.255.255.0 172.16.2.0 255.255.255.0
ASA(config)# class-map tcp_bypass
ASA(config-cmap)# match access-list tcp_bypass_range
ASA(config-cmap)# policy-map tcp_bypass_policy
ASA(config-pmap)# class tcp_bypass
ASA(config-pmap-c)# set connection advanced-options tcp-state-bypass
ASA(config-pmap-c)# service-policy tcp_bypass_policy interface inside
Again verification from R1:
test_host#telnet 172.16.2.2
Trying 172.16.2.2 ... Open
Password required, but none set
Monitoring output from ASA:
ASA# show conn
2 in use, 2 most used
TCP inside 172.16.2.2:23 inside 172.16.1.200:39415, idle 0:02:56, bytes 24, flags b
TCP inside 172.16.2.2:23 inside 172.16.1.200:27919, idle 0:03:26, bytes 24, flags b
*If you use the show conn command, the display for connections that use TCP state bypass includes the flag "b."
Hair-pinning is when ASA appliance is receiving traffic on an interface and immediately sending traffic back out the same interface.
This feature could be enabled by using the following command:
ASA(config)# same-security-traffic permit intra-interface
Encrypted traffic can be redirected through same interface as encrypted and as a clear traffic - feature from ASA software version 7.2(1). Hair-pinning is useful for many different scenarios.
Let's consider following scenario.
R1 which is our test host is connected to ASA inside interface and same ASA interface is attached to R2. I know, looks a bit weird, but this is just simple scenario for the feature test.
ASA has route for network 172.16.2.0 over the router R2 (172.16.1.100)
ASA(config)# route inside 172.16.2.0 255.255.255.0 172.16.1.100
R1 has ASA 172.16.1.1 inside interface configured as default gateway.
Basic connectivity check:
ASA# ping 172.16.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 10/24/30 ms
ASA#
test_host#ping 172.16.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.2.2, timeout is 2 seconds:
.....
Success rate is 0 percent (0/5)
test_host#
To make this working, hair-pinning has to be enabled. Before enabling the feature, I would like to check few more things. What about telnet from R2 and R1 (test_host) to R3 interface 172.16.2.2.
R2#telnet 172.16.2.2
Trying 172.16.2.2 ... Open
Password required, but none set
[Connection to 172.16.2.2 closed by foreign host]
test_host#telnet 172.16.2.2
Trying 172.16.2.2 ...
% Connection timed out; remote host not responding
test_host#
Packet tracer from ASA:
ASA# packet-tracer input inside tcp 172.16.2.200 6666 172.16.2.2 telnet detailed
...
Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: inside
output-status: up
output-line-status: up
Action: drop
Drop-reason: (acl-drop) Flow is denied by configured rule
Obviosuly, packet is not reaching R3 (I would like to see what is happening from R3 perspective with debug ip packet command). Same test again:
R3#debug ip packet
IP packet debugging is on
R3#
test_host#telnet 172.16.2.2
Trying 172.16.2.2 ...
R3#debug ip packet
IP packet debugging is on
R3#
Hmm, nothing. Let's allow hair-pinning on ASA itself:
ASA(config)# same-security-traffic permit intra-interface
icmp test from R1:
test_host#ping 172.16.2.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 172.16.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 28/42/60 ms
test_host#
telnet attempt is reaching R3 (just reaching, session is not established):
test_host#telnet 172.16.2.2
Trying 172.16.2.2 ...
Packets are indeed reaching R3:
R3#
*Mar 1 00:53:55.463: IP: tableid=0, s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), routed via RIB
*Mar 1 00:53:55.463: IP: s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), len 44, rcvd 3
*Mar 1 00:53:55.471: IP: tableid=0, s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), routed via FIB
*Mar 1 00:53:55.471: IP: s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), len 44, sending
*Mar 1 00:53:55.551: IP: tableid=0, s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), routed via RIB
*Mar 1 00:53:55.551: IP: s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), len 40, rcvd 3
R3#
*Mar 1 00:53:57.459: IP: tableid=0, s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), routed via RIB
*Mar 1 00:53:57.463: IP: s=172.16.1.200 (FastEthernet0/1), d=172.16.2.2 (FastEthernet0/1), len 44, rcvd 3
*Mar 1 00:53:57.463: IP: tableid=0, s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), routed via FIB
*Mar 1 00:53:57.467: IP: s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), len 40, sending
*Mar 1 00:53:57.475: IP: tableid=0, s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), routed via FIB
*Mar 1 00:53:57.475: IP: s=172.16.2.2 (local), d=172.16.1.200 (FastEthernet0/1), len 44, sending
Packet tracer from ASA:
ASA(config)# packet-tracer input inside tcp 172.16.2.200 6666 172.16.2.2 telnet detailed
...
Result:
input-interface: inside
input-status: up
input-line-status: up
output-interface: inside
output-status: up
output-line-status: up
Action: allow
So, perfect! Did I say everything is fine? Well, yes and no.... My telnet is getting to R3 but connectivity is not fully working. Why? Whireshark will help us to get answer on this question.
I am running Wireshark on router R3 interface where R2 is attached:
Wireshark Output from R3 |
R1 (172.16.1.200) is sending SYN packet
R3 (172.16.2.2) is sending back SYN/ACK
R1 (172.16.1.200) is sending RST
Looks like SYN/ACK is not passing ASA, instead it is leaving switch and going straight to R1. We do have asymmetric scenario. Solution is TCP State Bypass feature.
According to the Cisco, TCP State Bypas requires following steps:
1. Use the class-map class_map_name command in order to create a class map. The class map is used to identify the traffic for which you want to disable stateful firewall inspection. The class map used in this example is tcp_bypass.
ASA(config)#class-map tcp_bypass
2. Use the match parameter command in order to specify interesting traffic in the class map. When using the Modular Policy Framework, use the match access-list command in class-map configuration mode in order to use an access list to identify traffic to which you want to apply actions. Here is an example of this configuration:
ASA(config)#class-map tcp_bypass
ASA(config-cmap)#match access-list tcp_bypass
tcp_bypass is the name of the access-list used in this example. Refer to Identifying Traffic (Layer 3/4 Class Map) for more information on specifying the interesting traffic.
3. Use the policy-map name command in order to add a policy map or edit a policy map (which is already present) that sets the actions to take with the class map traffic specified already. When using the Modular Policy Framework, use the policy-map command (without the type keyword) in global configuration mode in order to assign actions to traffic that you identified with a Layer 3/4 class map (the class-map or class-map type management command). In this example, the policy map is tcp_bypass_policy:
ASA(config-cmap)#policy-map tcp_bypass_policy
4. Use the class command in policy-map configuration mode in order to assign the class map (tcp_bypass) already created to the policy map (tcp_bypass_policy) where you can assign actions to the class map traffic . In this example, the class map is tcp_bypass:
ASA(config-cmap)#policy-map tcp_bypass_policy
ASA(config-pmap)#class tcp_bypass
5. Use the set connection advanced-options tcp-state-bypass command in class configuration mode in order to enable the TCP state bypass feature. This command was introduced in version 8.2(1). The class configuration mode is accessible from the policy-map configuration mode as shown in this example:
ASA(config-cmap)#policy-map tcp_bypass_policy
ASA(config-pmap)#class tcp_bypass
ASA(config-pmap-c)#set connection advanced-options tcp-state-bypass
6.Use the service-policy policymap_name [ global | interface intf ] command in global configuration mode in order to activate a policy map globally on all interfaces or on a targeted interface. In order to disable the service policy, use the no form of this command. Use the service-policy command to enable a set of policies on an interface.global applies the policy map to all interfaces, and interface applies the policy to one interface. Only one global policy is allowed. You can override the global policy on an interface by applying a service policy to that interface. You can apply only one policy map to each interface.
ASA(config-pmap-c)#service-policy tcp_bypass_policy outside
Our configuration example is:
ASA(config)# access-list tcp_bypass_range extended permit tcp 172.16.1.0 255.255.255.0 172.16.2.0 255.255.255.0
ASA(config)# class-map tcp_bypass
ASA(config-cmap)# match access-list tcp_bypass_range
ASA(config-cmap)# policy-map tcp_bypass_policy
ASA(config-pmap)# class tcp_bypass
ASA(config-pmap-c)# set connection advanced-options tcp-state-bypass
ASA(config-pmap-c)# service-policy tcp_bypass_policy interface inside
test_host#telnet 172.16.2.2
Trying 172.16.2.2 ... Open
Password required, but none set
Monitoring output from ASA:
ASA# show conn
2 in use, 2 most used
TCP inside 172.16.2.2:23 inside 172.16.1.200:39415, idle 0:02:56, bytes 24, flags b
TCP inside 172.16.2.2:23 inside 172.16.1.200:27919, idle 0:03:26, bytes 24, flags b
*If you use the show conn command, the display for connections that use TCP state bypass includes the flag "b."
No comments:
Post a Comment