Skip to content

GRE Tunnel and NAT

GRE (Generic Routing Encapsulation) is a tunneling protocol (IP protocol 47) that encapsulates one network protocol inside another. In RouterOS, GRE tunnels are commonly used to:

  • Create site-to-site VPN links between routers with public IP addresses
  • Carry routing protocols (OSPF, BGP) over plain or encrypted tunnels
  • Build hub-and-spoke topologies

GRE provides no encryption. For encrypted tunnels, combine GRE with IPsec or use WireGuard or SSTP instead.

Because GRE uses IP protocol 47 — not TCP or UDP — standard port-based NAT tracking does not apply. Two common problems arise when combining GRE tunnels with NAT on RouterOS:

  1. Tunnel traffic gets masqueraded — packets leaving the router through the GRE interface are NATted before they reach the tunnel endpoint, breaking the tunnel.
  2. One end is behind NAT — the remote GRE peer cannot reach the local endpoint because the upstream NAT device does not forward IP protocol 47.

This document covers how to configure NAT rules correctly so GRE tunnels function alongside masquerade, and what to do when one side of the tunnel is behind a NAT device.

  • RouterOS v6.49 or later (examples work on v7 without modification)
  • A working GRE tunnel interface (/interface gre)
  • Masquerade or srcnat configured on the WAN interface
  • For GRE+IPsec: IPsec peer and policy already configured

Create the GRE interface on each router. Replace 1.1.1.1 (HQ public IP) and 2.2.2.2 (branch public IP) with your actual addresses.

HQ router (1.1.1.1):

/interface gre
add name=gre-branch local-address=1.1.1.1 remote-address=2.2.2.2 \
keepalive=10s,10 clamp-tcp-mss=yes
/ip address
add address=10.99.0.1/30 interface=gre-branch
/ip route
add dst-address=192.168.20.0/24 gateway=gre-branch

Branch router (2.2.2.2):

/interface gre
add name=gre-hq local-address=2.2.2.2 remote-address=1.1.1.1 \
keepalive=10s,10 clamp-tcp-mss=yes
/ip address
add address=10.99.0.2/30 interface=gre-hq
/ip route
add dst-address=192.168.10.0/24 gateway=gre-hq

If masquerade is active on the WAN interface, you must add an accept rule above the masquerade rule to prevent GRE tunnel packets from being NATted.

Exempt traffic that routes over the GRE interface:

/ip firewall nat
add chain=srcnat out-interface=gre-branch action=accept comment="GRE tunnel — no NAT" place-before=0

Alternatively, exempt by destination network:

/ip firewall nat
add chain=srcnat dst-address=192.168.20.0/24 action=accept comment="GRE to branch — no NAT" place-before=0

Verify rule order — the accept rule must appear before any masquerade rule in the srcnat chain:

/ip firewall nat print

When the branch router is behind a third-party NAT device (e.g., a cable modem or CGNAT), configure remote-address on HQ to the public IP of the upstream NAT device, not the branch router’s LAN IP.

The upstream NAT device must forward IP protocol 47 to the branch router. Most consumer routers call this “GRE passthrough” — enable it if the option exists.

Branch router behind NAT (192.168.1.100 on LAN, upstream NAT is 2.2.2.2):

/interface gre
add name=gre-hq local-address=192.168.1.100 remote-address=1.1.1.1 \
keepalive=10s,10 clamp-tcp-mss=yes

HQ router still uses the NAT’s public IP as remote:

/interface gre
add name=gre-branch local-address=1.1.1.1 remote-address=2.2.2.2 \
keepalive=10s,10 clamp-tcp-mss=yes

When GRE is wrapped in IPsec (a common site-to-site pattern), add an IPsec bypass rule above the masquerade rule. Without this rule, masquerade rewrites the source address before IPsec encrypts the packet, causing decryption failures at the remote end.

/ip firewall nat
add chain=srcnat action=accept ipsec-policy=out,ipsec \
comment="IPsec bypass — do not masquerade" place-before=0

Full srcnat chain order for a router with GRE+IPsec and internet masquerade:

/ip firewall nat print
# Expected order:
# 0 chain=srcnat action=accept ipsec-policy=out,ipsec
# 1 chain=srcnat out-interface=gre-branch action=accept
# 2 chain=srcnat out-interface=ether1 action=masquerade

Allow GRE protocol in the input chain so keepalives and encapsulated packets reach the router:

/ip firewall filter
add chain=input protocol=gre action=accept comment="Allow GRE" place-before=0

If restricting by source:

/ip firewall filter
add chain=input protocol=gre src-address=2.2.2.2 action=accept comment="GRE from branch"

Check that the tunnel interface is up and running:

/interface gre print
# R flag = running

Confirm the tunnel address is reachable from both ends:

/ping 10.99.0.2 interface=gre-branch count=4

Check NAT rule hit counters — the accept rule should increment when tunnel traffic flows, and the masquerade rule should NOT increment for tunnel traffic:

/ip firewall nat print stats

For GRE+IPsec, verify that IPsec SAs are installed:

/ip ipsec installed-sa print

Use the packet sniffer on the WAN interface to confirm raw GRE (protocol 47) frames are present and not mangled:

/tool sniffer quick interface=ether1 ip-protocol=gre

Tunnel comes up but traffic does not pass

Check that the NAT exemption rule exists and is ordered before masquerade:

/ip firewall nat print

If masquerade is incrementing for tunnel destination addresses, the accept rule is missing or in the wrong position.

Keepalive fails — tunnel stays down

  1. Verify the remote router’s input chain accepts GRE (protocol=gre).
  2. Confirm the upstream NAT device supports GRE passthrough.
  3. Use /tool sniffer on the WAN to check whether protocol 47 arrives.
  4. If behind CGNAT, plain GRE will not work — switch to WireGuard or SSTP.

GRE+IPsec — tunnel up but traffic dropped

Confirm the IPsec bypass NAT rule is present and ordered first:

/ip firewall nat print where ipsec-policy=out,ipsec

Check IPsec policy is matching traffic:

/ip ipsec policy print stats

Disable fasttrack temporarily to rule out fasttrack bypassing IPsec:

/ip firewall filter set [find comment="fasttrack"] disabled=yes

One-way traffic through GRE

Both routers must have symmetric NAT exemption rules. Check the far end as well. Asymmetric routes can also cause this — verify both directions with /tool traceroute through the tunnel interface.

MTU / fragmentation issues

GRE adds a 24-byte header. If the WAN MTU is 1500, the effective tunnel MTU is 1476. Enable MSS clamping on the tunnel and set an explicit MTU if needed:

/interface gre set gre-branch clamp-tcp-mss=yes mtu=1476