Skip to content
MikroTik RouterOS Docs

GRE Tunnel: Complete Site-to-Site Configuration Guide

For the impatient: here’s the 30-second version.

# Site A (192.168.80.1)
/interface gre add name=gre-siteB remote-address=192.168.90.1 local-address=192.168.80.1
/ip address add address=172.16.1.1/30 interface=gre-siteB
/ip route add dst-address=10.1.202.0/24 gateway=172.16.1.2
# Site B (192.168.90.1)
/interface gre add name=gre-siteA remote-address=192.168.80.1 local-address=192.168.90.1
/ip address add address=172.16.1.2/30 interface=gre-siteA
/ip route add dst-address=10.1.101.0/24 gateway=172.16.1.1

GRE (Generic Routing Encapsulation) is a tunneling protocol that encapsulates IP and IPv6 packets inside IP packets, creating point-to-point virtual links between routers. Unlike EoIP (Ethernet over IP), GRE operates at Layer 3 and only forwards IP/IPv6 traffic - not full Ethernet frames.

GRE is an industry standard defined in RFC 2784, making it compatible with routers from other vendors including Cisco, Juniper, and others. This interoperability makes GRE the preferred choice when connecting MikroTik routers to non-MikroTik equipment.

Key characteristics:

  • Overhead: 24 bytes (4-byte GRE header + 20-byte IP header)
  • Protocol: IP Protocol 47
  • Encryption: None (use IPsec for security)
  • Bridging: Not supported (use EoIP for Layer 2)

GRE Limitations

  • NAT traversal: GRE cannot traverse standard NAT (no port numbers). Use IPsec NAT-T or ensure direct IP connectivity.
  • ISP blocking: Some ISPs block IP protocol 47. Test with ping using GRE before deployment.
  • No encryption: Traffic is transmitted in clear text. Always combine with IPsec for sensitive data.

GRE creates a virtual point-to-point link by encapsulating the original IP packet inside a new IP packet with a GRE header. The outer IP header uses the tunnel endpoint addresses, while the inner packet travels unchanged.

+------------------+------------+------------------+
| Outer IP Header | GRE Header | Original Packet |
| (Tunnel IPs) | (4 bytes) | (Your Data) |
+------------------+------------+------------------+

GRE is inherently stateless - without keepalives, the tunnel interface always shows “running” even if the remote endpoint is unreachable. This can cause black hole routing where traffic enters the tunnel but never reaches its destination.

RouterOS adds keepalive functionality to detect remote endpoint failures:

SettingBehavior
keepalive=10s,10Check every 10s, mark down after 10 failures (100s)
keepalive=5s,3Check every 5s, mark down after 3 failures (15s)
keepalive=0Disabled (always shows running)
FeatureGREIPIPEoIP
Layer3 (IP)3 (IP)2 (Ethernet)
Overhead24 bytes20 bytes42 bytes
PayloadIP/IPv6IP onlyFull Ethernet
BridgeableNoNoYes
StandardsRFC 2784RFC 2003MikroTik proprietary
Cisco CompatibleYesYesNo
KeepaliveYesYesYes

When to use GRE:

  • Site-to-site routing between locations
  • Connecting to non-MikroTik routers (Cisco, Juniper, etc.)
  • BGP or OSPF peering over tunnels
  • When you need standards-compliant tunneling

When to use EoIP instead:

  • Extending Layer 2 networks across sites
  • Bridging VLANs between locations
  • Running non-IP protocols (legacy systems)

This guide configures a tunnel between two sites:

Site A Internet Site B
+-------------------+ +-------------------+
| LAN: 10.1.101.0/24| +-----------------+ | LAN: 10.1.202.0/24|
| Router: 192.168.80.1|---| ISP/Internet |-------| Router: 192.168.90.1|
| | +-----------------+ | |
| Tunnel: 172.16.1.1|<======= GRE Tunnel =========>| Tunnel: 172.16.1.2|
+-------------------+ +-------------------+

Tunnel addressing: 172.16.1.0/30 for the point-to-point link between routers.

Routing logic:

  • Traffic to 10.1.202.0/24 from Site A goes via GRE tunnel to Site B
  • Traffic to 10.1.101.0/24 from Site B goes via GRE tunnel to Site A
  • Both routers have public IP addresses (or private IPs with direct routing)
  • IP connectivity between tunnel endpoints
  • GRE protocol (IP Protocol 47) allowed through all firewalls in the path
  • Basic understanding of IP routing and subnetting

Create the GRE tunnel interface on both routers, specifying the local and remote endpoint addresses.

Site A:

/interface gre add name=gre-siteB \
remote-address=192.168.90.1 \
local-address=192.168.80.1 \
keepalive=10s,10

Site B:

/interface gre add name=gre-siteA \
remote-address=192.168.80.1 \
local-address=192.168.90.1 \
keepalive=10s,10

Add IP addresses to the tunnel interfaces for routing:

Site A:

/ip address add address=172.16.1.1/30 interface=gre-siteB

Site B:

/ip address add address=172.16.1.2/30 interface=gre-siteA

Configure routes to reach the remote LAN networks:

Site A:

/ip route add dst-address=10.1.202.0/24 gateway=172.16.1.2

Site B:

/ip route add dst-address=10.1.101.0/24 gateway=172.16.1.1

Allow GRE protocol through the firewall:

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

Verify the GRE interface is running:

/interface gre print

Expected Output:

Flags: X - disabled, R - running
0 R name="gre-siteB" mtu=1476 local-address=192.168.80.1
remote-address=192.168.90.1 keepalive=10s,10 dscp=inherit
clamp-tcp-mss=yes dont-fragment=no allow-fast-path=yes

The R flag indicates the tunnel is running.

Test basic tunnel connectivity:

/ping 172.16.1.2 count=3

Expected Output:

SEQ HOST SIZE TTL TIME STATUS
0 172.16.1.2 56 64 25ms
1 172.16.1.2 56 64 24ms
2 172.16.1.2 56 64 26ms
sent=3 received=3 packet-loss=0% min-rtt=24ms avg-rtt=25ms max-rtt=26ms

Verify traffic flows to the remote LAN:

/ping 10.1.202.1 src-address=10.1.101.1 count=3

Confirm routes are active:

/ip route print where gateway~"172.16.1"

Expected Output:

Flags: D - dynamic, A - active, c - connect, S - static
# DST-ADDRESS GATEWAY DISTANCE
0 A S 10.1.202.0/24 172.16.1.2 1

GRE provides no encryption. For secure tunnels, combine with IPsec using the built-in ipsec-secret parameter:

/interface gre add name=gre-secure \
remote-address=192.168.90.1 \
local-address=192.168.80.1 \
ipsec-secret=YourStrongSecretKey \
allow-fast-path=no
/ip address add address=172.16.1.1/30 interface=gre-secure

Important: Set allow-fast-path=no when using IPsec - fast path bypasses IPsec processing.

For manual IPsec configuration (more control over encryption settings):

# Create GRE tunnel
/interface gre add name=gre-manual remote-address=192.168.90.1 \
local-address=192.168.80.1 allow-fast-path=no
# Configure IPsec peer
/ip ipsec peer add address=192.168.90.1 exchange-mode=ike2
# Configure IPsec policy for GRE traffic
/ip ipsec policy add src-address=192.168.80.1/32 \
dst-address=192.168.90.1/32 protocol=gre action=encrypt

Use dynamic routing over the GRE tunnel:

# Create tunnel
/interface gre add name=gre-ospf remote-address=192.168.90.1 \
local-address=192.168.80.1
/ip address add address=10.0.0.1/30 interface=gre-ospf
# Configure OSPF over tunnel
/routing ospf instance add name=default router-id=192.168.80.1
/routing ospf area add name=backbone area-id=0.0.0.0 instance=default
/routing ospf interface-template add networks=10.0.0.0/30 area=backbone

For BGP peering over GRE:

# Create tunnel
/interface gre add name=gre-bgp remote-address=203.0.113.1 \
local-address=198.51.100.1
/ip address add address=10.255.255.1/30 interface=gre-bgp
# Configure BGP session over tunnel
/routing bgp connection add name=bgp-peer \
remote.address=10.255.255.2 \
local.role=ebgp as=65001

For IPv6 transport:

/interface gre6 add name=gre6-tunnel \
local-address=2001:db8::1 \
remote-address=2001:db8::2
# Assign IPv4 over IPv6 tunnel
/ip address add address=10.255.0.1/30 interface=gre6-tunnel
# Or IPv6-in-IPv6
/ipv6 address add address=fd00::1/64 interface=gre6-tunnel

For faster failover detection:

/interface gre set gre-siteB keepalive=5s,3

This checks every 5 seconds and marks the tunnel down after 3 failures (15 seconds total).

GRE adds 24 bytes overhead. For a 1500-byte path MTU:

/interface gre set gre-siteB mtu=1476

Enable TCP MSS clamping to prevent fragmentation issues:

/interface gre set gre-siteB clamp-tcp-mss=yes

Symptoms: GRE interface has R flag but pings through tunnel fail.

Solutions:

  1. Check keepalive: Without keepalive, tunnel always shows running
    /interface gre set gre-tunnel keepalive=10s,10
  2. Check firewall: Ensure GRE (protocol 47) is allowed
    /ip firewall filter print where protocol=gre
  3. Check routing: Verify routes exist on both sides
    /ip route print where gateway~"gre"

Symptoms: Interface shows X (disabled) or no R flag.

Solutions:

  1. Verify endpoint connectivity:
    /ping 192.168.90.1
  2. Check local-address exists:
    /ip address print where address~"192.168.80.1"
  3. Verify GRE not blocked by ISP: Some ISPs block protocol 47
  4. Check NAT: GRE cannot traverse typical NAT without IPsec-NAT-T

Symptoms: Ping works one direction only.

Solutions:

  1. Check routes on both routers: Each side needs return routes
  2. Verify tunnel addresses: Ensure /30 subnet is correctly configured
  3. Check for NAT issues: Verify source addresses aren’t being NATed

Symptoms: Small packets work, large transfers fail or stall.

Solutions:

  1. Lower MTU:
    /interface gre set gre-tunnel mtu=1400
  2. Enable MSS clamping:
    /interface gre set gre-tunnel clamp-tcp-mss=yes
  3. Test path MTU:
    /ping 172.16.1.2 size=1400 do-not-fragment

Symptoms: GRE tunnel works without IPsec but fails with ipsec-secret.

Solutions:

  1. Disable fast path:
    /interface gre set gre-tunnel allow-fast-path=no
  2. Check IPsec policies:
    /ip ipsec policy print
    /ip ipsec installed-sa print
  3. Allow IKE/ESP through firewall:
    /ip firewall filter add chain=input protocol=udp dst-port=500,4500 action=accept
    /ip firewall filter add chain=input protocol=ipsec-esp action=accept

Symptoms: Tunnel state column empty (not “R”) after upgrade.

Solutions:

  1. Temporarily disable keepalive:
    /interface gre set gre-tunnel keepalive=0
  2. Update RouterOS: Keepalive issues were fixed in later releases
  3. Check both endpoints: Both must run compatible versions
# View GRE interface details
/interface gre print detail
# Monitor interface in real-time
/interface gre monitor gre-tunnel
# Check interface counters
/interface print stats where name~"gre"
# View routing table entries via tunnel
/ip route print where gateway~"gre"
# Test with specific source
/ping 10.1.202.1 src-address=10.1.101.1
# Packet capture on tunnel
/tool sniffer quick interface=gre-tunnel

GRE transmits data in clear text. For sensitive traffic:

  • Use ipsec-secret for automatic IPsec
  • Configure manual IPsec policies for more control
  • Consider WireGuard or IPsec-only tunnels for security-critical applications
# Accept GRE only from known peers
/ip firewall filter add chain=input protocol=gre \
src-address=192.168.90.1 action=accept comment="GRE from Site B"
# Drop GRE from unknown sources
/ip firewall filter add chain=input protocol=gre action=drop
# Restrict what can traverse the tunnel
/ip firewall filter add chain=forward in-interface=gre-siteB \
dst-port=22,80,443 protocol=tcp action=accept
/ip firewall filter add chain=forward in-interface=gre-siteB action=drop

Limit which networks can use the tunnel:

/ip firewall filter add chain=forward src-address=10.1.101.0/24 \
out-interface=gre-siteB action=accept
/ip firewall filter add chain=forward out-interface=gre-siteB action=drop
PropertyTypeDefaultDescription
namestring-Interface name
remote-addressIP-Remote tunnel endpoint (required)
local-addressIP0.0.0.0Local source address (auto if unset)
disabledyes/nonoEnable/disable interface
mtuinteger1476Layer 3 MTU
keepalivetime,retries10s,10Format: interval,retry-count
dscpinherit/0-63inheritDSCP value for outer packets
clamp-tcp-mssyes/noyesAdjust TCP MSS automatically
dont-fragmentinherit/nonoDF bit handling
allow-fast-pathyes/noyesHardware acceleration (disable for IPsec)
ipsec-secretstring-Pre-shared key (auto-creates IPsec)
commentstring-Description