I found below:
https://community.checkpoint.com/t5/Security-Gateways/NAT-Loopback-Hairpin-NAT/m-p/238179
https://community.checkpoint.com/t5/General-Topics/Hairpin-NAT-is-not-working/m-p/207912
This AI answer seems pretty decent to me:
There are three practical ways to solve this depending on what you can change in your environment. I’ll explain why the gateway SNATs, show the Check Point NAT approach to preserve the original client IP, and then give two safer/cleaner alternatives (and their tradeoffs).
Why the server sees the gateway IP
When an internal client connects to the server’s public IP:
-
The gateway destination-NATs the destination to the internal server IP.
-
If the server replies directly to the client’s private IP (not via the gateway) the TCP conversation breaks (client expected replies from the public IP).
-
To make replies return through the gateway (so it can reverse the destination NAT), the gateway often performs source NAT (hide/SNAT) of the client to the gateway IP. That guarantees the server’s reply goes back to the gateway, which then reverses NAT and sends it to the client — but now the server sees the gateway IP as the source.
This behavior and the SK that documents NAT loopback for Check Point are described in SK110019. Check Point Support
Option A — Keep the original client IP (Manual NAT + proper routing)
This is the approach that can preserve original client IPs in server logs — but only if the server’s routing forces replies back through the firewall.
Steps (Check Point / SmartConsole manual NAT style):
-
Keep your existing external→internal static NAT that publishes the server on the public IP (so Internet users keep working).
-
Add a Manual NAT rule (place it above the automatic/Global rules) to handle internal clients hitting the public IP:
-
Original Source: <internal_VLAN_subnets> (or an object group containing all VLAN networks)
-
Original Destination: <public_IP_of_server>
-
Translated Destination: <internal_IP_of_server>
-
Translated Source: Original (i.e. do not change the source) — this is the key.
In SmartConsole the Translated Source column should be set to Original or “No translation” for that traffic.
-
Make sure the server’s return path to those internal VLANs goes through the firewall. Concretely:
Why this works: the request arrives at the gateway, destination-NAT translates to the server IP while keeping client source intact; the server replies to the client IP but because the server sends the packets to the firewall (via its gateway or a specific route), replies will traverse the firewall and be handled in the same connection tracking entry — the gateway reverses destination NAT and the client sees responses from the expected public IP while the server saw the original client IP in its logs.
Caveats:
-
If the server has a direct route back to a client subnet (i.e., not via the firewall), replies will bypass the firewall and the TCP session will fail. That’s the usual reason admins see gateway IP logged: to force replies back through the gateway the gateway performs SNAT by default.
-
If you have many VLANs, you must ensure the server has routes for all of them via the firewall (or the firewall is the server’s default gateway).
-
You must place the Manual NAT rule correctly (above auto/Global rules).
Relevant Check Point doc and community posts describing both SK110019 and user experiences. Check Point Support+1
Option B — Split-horizon (internal) DNS — recommended where feasible
Instead of forcing hairpin NAT, configure internal DNS so the public hostname resolves to the server’s private IP for internal clients (per VLAN if needed). That is the cleanest solution:
-
Clients access the server via internal IP (no hairpin).
-
No NAT translation for internal→internal traffic.
-
Server logs contain the real client IP.
-
No special NAT or routing gymnastics.
Tradeoffs:
-
You need to manage internal DNS views (or per-VLAN DNS overrides).
-
If you have many VLANs or multiple DNS servers that’s additional administrative work, but it’s the most robust and performant solution.
Many shops prefer split-horizon DNS specifically to avoid hairpin compromises (it’s the usual best practice). Server Fault
Option C — Accept SNAT and map logs back (if you cannot change routing/DNS)
If you cannot change DNS or the server routing, you may be forced to accept SNAT (server will see gateway IP). In that case:
Tradeoffs:
-
Adds components (proxy, LB) or more log correlation work.
-
Not as clean as preserving IP in the web server access logs.
Community notes call this the typical "disadvantage" of hairpin NAT — connectivity works but server loses the original source IP. Check Point CheckMates+1
Example SmartConsole manual NAT rule (illustrative)
(You don’t need to match labels exactly, just the idea)
Manual NAT rule (placed above automatic NAT rules):
-
Original Source: VLANs_Networks (e.g. 10.10.0.0/16, 10.20.0.0/16, …)
-
Original Destination: Server_Public_IP (object)
-
Service: HTTP/HTTPS
-
Translated Destination: Server_Private_IP
-
Translated Source: Original ← do not hide/SNAT
Then verify:
Short checklist you can run through right now
-
Create manual NAT rule as shown (Translated Source = Original).
-
Ensure server routes to all client VLANs via the firewall (server default gateway is firewall is easiest).
-
Install policy and test from one VLAN.
-
If server still sees gateway IP, check server routing (it is replying directly to client). If replies bypass the firewall you’ll need to add routes or use split-horizon DNS.
-
If you cannot change routes/DNS, consider reverse proxy + X-Forwarded-For or server-side log correlation.
Best,
Andy