Solved
Is there a guide to make virtual IPs work on SSL VPN interfaces?
Hello,
We have two questions:
- Is there a guide to make virtual IPs work on SSL VPN interfaces?
- May hairpin NAT work using secondary IP interfaces?
We are trying to make hairpin NAT work on 3000F. Any help will be much appreciated.
We followed this KB on hairpin NAT (https://community.fortinet.com/t5/FortiGate/Technical-Tip-Configuring-Hairpin-NAT-VIP/ta-p/195448#M2442). Our use case is similar to Example 1.
Campus1 (VPN / LAN IPs) --- FW (WAN IPs) -- internalServer (VIP).
At the FortiGate side, the VPN tunnels land on an SSL interface (ssl.root); ssl.root is defined on a WAN interface (port35).
Two firewall policies are defined:
- a NAT ingress rule, from ssl.root to port35, allowing internal users (VPN admin pool) to reach the virtual IP (defined as destination address object) balancing on an internal server.
- an egress rule, from port35 to a DMZ, allowing the NAT'ed requests to reach the load balancer virtual IP.
This translates into these policies:
# show firewall policy 1 config firewall policy edit 96 set uuid 40edc776-13ac-51f0-4ffe-76f817f3a8fb set srcintf "ssl.root" set dstintf "port35" set action accept set srcaddr "VPN admin pool" set dstaddr "internal-vip" set schedule "always" set service "SVC_HTTP" set logtraffic all set nat enable set ippool enable set poolname "PRIMARY" next end # show firewall address internal-vip config firewall address edit "aichor-dataplane-vip" set uuid b89f3c46-13ac-51f0-a148-d5b310b9adee set associated-interface "port35" set color 1 set subnet 5.23.18.38 255.255.255.255 next end
# show firewall policy 2 config firewall policy edit 93 set uuid bde1c42c-9556-51f0-1920-baa5f4d44b9f set srcintf "port35" set dstintf "DMZ" set action accept set srcaddr "RFC1918" "WAN_primary_ip" set dstaddr "external-vip-https" set schedule "always" set service "SVC_NGINX_EXT_HTTP_TCP_32443" set inspection-mode proxy set logtraffic all next end
# show firewall vip external-vip-https config firewall vip edit "external-vip-https" set uuid 5508607c-1f64-51f0-b372-bc95c2b4275d set type server-load-balance set server-type tcp set extip 5.23.18.39 set extintf "any" set monitor "nginx-internal-ingress-hc-tcp-32444" "ping" set extport 443 config realservers edit 1 set ip 10.120.0.16 set port 32444 set max-connections 1000 next edit 2 set ip 10.120.0.151 set port 32444 set status standby set max-connections 1000 next edit 3 set ip 10.120.1.149 set port 32444 set status standby set max-connections 1000 next end next end
We were expecting policy ID 1 to match first, then policy ID 2. We observed policy ID 2 got directly matched.
# diagnose firewall iprope lookup 10.120.37.1 12345 5.23.18.39 443 tcp ssl.root <src [10.120.37.1-12345] dst [85.233.198.42-443] proto tcp dev ssl.root> matches policy id: 0
# diagnose firewall iprope lookup 10.120.37.2 12355 5.23.18.39 443 tcp port35 <src [10.120.37.2-12355] dst [85.233.198.43-443] proto tcp dev port35> matches policy id: 2
To work around the mismatch, we added the internal IPs in srcaddr of policy ID 2 (the address object RFC1918), and see this message in diag debug flow
id=65308 trace_id=144 func=fw_pre_route_handler line=191 msg="VIP-10.120.0.123:32443, outdev-unknown"
A complete extract,
# diagnose debug flow trace start 5 # id=65308 trace_id=144 func=print_pkt_detail line=6005 msg="vd-root:0 received a packet(proto=6, 10.120.37.1:50042->5.23.18.39:443) tun_id=0.0.0.0 from ssl.root. flag [S], seq 856634200, ack 0, win 64240" id=65308 trace_id=144 func=init_ip_session_common line=6206 msg="allocate a new session-3dcd1101" id=65308 trace_id=144 func=__iprope_tree_check line=524 msg="gnum-100004, use int hash, slot=69, len=13" id=65308 trace_id=144 func=get_new_addr line=1280 msg="find SNAT: IP-5.23.18.36(from IPPOOL), port-50042" id=65308 trace_id=144 func=fw_pre_route_handler line=191 msg="VIP-10.120.0.123:32443, outdev-unknown" id=65308 trace_id=144 func=__ip_session_run_tuple line=3525 msg="DNAT 5.23.18.38:443->10.120.0.123:32443" id=65308 trace_id=144 func=__vf_ip_route_input_rcu line=1989 msg="find a route: flag=00000000 gw-0.0.0.0 via DATA" id=65308 trace_id=144 func=__iprope_tree_check line=524 msg="gnum-100004, use int hash, slot=36, len=9" id=65308 trace_id=144 func=fw_forward_handler line=1002 msg="Allowed by Policy-2:" id=65308 trace_id=144 func=ip_session_confirm_final line=3179 msg="npu_state=0x100, hook=4"
As mentioned above, the addresses used in the VIPs are secondary IPs of port35; we are also wondering if the problem might come from that.
Your feedback is much appreciated,
Ariel
