· 8 min read

BGP Tunnel: GRE + BGP for DDoS-Protected IP Announcement

A BGP tunnel is a GRE tunnel between your router and a scrubbing provider, with an eBGP session running inside it. Your ASN announces your IP block through the provider, attack traffic is filtered upstream, and only clean traffic comes back to you over the tunnel.

This guide covers how the design works, what you need before you start, and example GRE + BGP configs for Linux (BIRD 2), MikroTik RouterOS v7, and Juniper Junos. It also covers the part that breaks most deployments: MTU and MSS.

All addresses below come from documentation ranges (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) and private ASNs from the AS64496 range. Replace them with your own values.

How a BGP tunnel works

Normally you announce a prefix to a transit provider over a physical or VLAN link. With a BGP tunnel, the "link" is a GRE tunnel over the public internet.

  1. Your router or server builds a GRE tunnel to the provider's tunnel endpoint.
  2. An eBGP session comes up over the tunnel's inner /30.
  3. You announce your prefix. The provider originates it from its own network, behind its DDoS mitigation.
  4. Inbound traffic for your prefix hits the provider first, gets filtered, and is forwarded to you inside GRE.
  5. Outbound traffic can leave through the tunnel (symmetric) or through your local upstream, depending on your design.

This works well when you can't get a cross-connect to a scrubbing location, or when your hosting provider doesn't let you change upstream routing. It's the approach behind Nixcon's NixGuard Edge service, which runs on AS40368. Details are on the DDoS protection and firewall page.

What you need first

Ownership checks are usually automated against ROAs and RIR/IRR data. At Nixcon, verified customer ASNs are added to the AS-NIXCON AS-SET. If your ROA or IRR data is missing or doesn't match, the session may come up but your prefix will be filtered. Fix the records first.

Example addressing

Item Value
Your ASN AS64496
Your prefix 203.0.113.0/24
Your tunnel endpoint (public) 192.0.2.10
Provider tunnel endpoint 198.51.100.1
Inner tunnel /30 169.254.100.0/30 (you: .2, provider: .1)
Provider ASN AS40368

Your provider supplies the real endpoint and inner addresses. Use those, not these.

MTU and MSS: do the math first

GRE over IPv4 adds 24 bytes: 20 for the outer IP header and 4 for the GRE header. On a standard 1500-byte path:

If your underlay MTU is lower (PPPoE, another tunnel, some cloud networks), subtract the difference. Confirm the recommended values with your provider, since the tunnel's far end must match.

If you skip this, small packets work, pings work, BGP comes up, and then large HTTPS responses stall. That's the classic MTU black hole.

Linux (iproute2 + BIRD 2)

Build the tunnel

# Pin the route to the tunnel endpoint on the physical interface (avoid recursion)
ip route add 198.51.100.1/32 via <your-underlay-gateway> dev eth0

ip tunnel add gre-nix mode gre local 192.0.2.10 remote 198.51.100.1 ttl 255
ip addr add 169.254.100.2/30 dev gre-nix
ip link set gre-nix mtu 1476 up

# Put the announced prefix on a dummy interface
ip link add dummy0 type dummy
ip link set dummy0 up
ip addr add 203.0.113.1/24 dev dummy0

Clamp MSS

iptables -t mangle -A FORWARD -o gre-nix -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1436
iptables -t mangle -A OUTPUT  -o gre-nix -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1436

Source-based return path

If you want replies from your prefix to leave via the tunnel:

ip rule add from 203.0.113.0/24 lookup 100
ip route add default via 169.254.100.1 dev gre-nix table 100

BIRD 2 session

router id 192.0.2.10;

protocol device { }

protocol static announce4 {
    ipv4;
    route 203.0.113.0/24 blackhole;
}

filter nix_out {
    if net = 203.0.113.0/24 then accept;
    reject;
}

filter nix_in {
    if net = 0.0.0.0/0 then accept;
    reject;
}

protocol bgp nixcon {
    local 169.254.100.2 as 64496;
    neighbor 169.254.100.1 as 40368;
    ipv4 {
        import filter nix_in;
        export filter nix_out;
    };
}

Adjust nix_in to the routes your session actually receives (default only, Nixcon routes only, or a full table). For deeper filter and policy examples, see our earlier BIRD 2 configuration guide.

MikroTik RouterOS v7

/interface gre add name=gre-nix local-address=192.0.2.10 remote-address=198.51.100.1 mtu=1476
/ip address add address=169.254.100.2/30 interface=gre-nix

/ip route add dst-address=203.0.113.0/24 blackhole
/ip firewall address-list add list=bgp-out address=203.0.113.0/24

/routing filter rule add chain=out-nix rule="if (dst == 203.0.113.0/24) { accept }"
/routing filter rule add chain=out-nix rule="reject"
/routing filter rule add chain=in-nix rule="if (dst == 0.0.0.0/0) { accept }"
/routing filter rule add chain=in-nix rule="reject"

/routing bgp connection add name=nixcon as=64496 router-id=192.0.2.10 \
    local.address=169.254.100.2 local.role=ebgp \
    remote.address=169.254.100.1 remote.as=40368 \
    output.network=bgp-out output.filter-chain=out-nix input.filter=in-nix

/ip firewall mangle add chain=forward action=change-mss new-mss=1436 \
    out-interface=gre-nix protocol=tcp tcp-flags=syn

Check that no firewall rule drops IP protocol 47 (GRE) from the provider endpoint. Allow it explicitly in the input chain.

Juniper Junos

GRE needs tunnel services on the platform (on MX, a tunnel-capable PIC or inline services). SRX devices use gr-0/0/0 directly.

set interfaces gr-0/0/0 unit 0 tunnel source 192.0.2.10
set interfaces gr-0/0/0 unit 0 tunnel destination 198.51.100.1
set interfaces gr-0/0/0 unit 0 family inet mtu 1476
set interfaces gr-0/0/0 unit 0 family inet address 169.254.100.2/30

set routing-options autonomous-system 64496
set routing-options static route 203.0.113.0/24 discard

set policy-options policy-statement NIX-OUT term 1 from route-filter 203.0.113.0/24 exact
set policy-options policy-statement NIX-OUT term 1 then accept
set policy-options policy-statement NIX-OUT term 2 then reject
set policy-options policy-statement NIX-IN term 1 from route-filter 0.0.0.0/0 exact
set policy-options policy-statement NIX-IN term 1 then accept
set policy-options policy-statement NIX-IN term 2 then reject

set protocols bgp group NIXCON type external
set protocols bgp group NIXCON peer-as 40368
set protocols bgp group NIXCON neighbor 169.254.100.1 local-address 169.254.100.2
set protocols bgp group NIXCON neighbor 169.254.100.1 import NIX-IN
set protocols bgp group NIXCON neighbor 169.254.100.1 export NIX-OUT

On SRX, clamp MSS with set security flow tcp-mss gre-in 1436 and set security flow tcp-mss gre-out 1436. Other platforms have their own TCP MSS adjustment for tunnel interfaces. Also permit GRE in your host-inbound or security policy configuration.

Verify the tunnel

Test the underlay path first, then the tunnel itself. A 1476-byte tunnel MTU means a 1448-byte ICMP payload (1476 − 20 IP − 8 ICMP) with DF set should pass:

ping -M do -s 1448 169.254.100.1
ping -M do -s 1449 169.254.100.1   # should fail

Then check BGP:

birdc show protocols nixcon
birdc show route export nixcon

Finally, confirm your prefix from the outside. The public Nixcon looking glass lets you run BGP route, ping, and traceroute queries from İzmir, Frankfurt, and the US. Look for your prefix with the expected origin ASN and path.

Common mistakes and fixes

Detect attacks, not just absorb them

Scrubbing is only part of the picture. Flow-based monitoring shows which destinations, ports, and protocols are being targeted, and helps you tell an attack from a traffic spike. NixMon provides flow-based network monitoring and DDoS detection that fits this kind of setup.

Where this fits

Use a BGP tunnel when you own an ASN and prefix, want DDoS-filtered inbound traffic, and can't or don't want to rent a dedicated cross-connect. If you don't have a router, a Linux VDS can terminate the tunnel and run BIRD, or you can announce directly from a BGP-enabled VDS. Nixcon operates AS40368 with a main data center in İzmir, Türkiye, and POPs in Frankfurt and Fremont, California, so you can pick a tunnel location close to your users or servers.

Frequently asked questions

What is a BGP tunnel?

A BGP tunnel is an eBGP session that runs inside a GRE tunnel between your router and a provider. You announce your own prefix with your own ASN, the provider filters attack traffic upstream, and clean traffic returns to you through the tunnel.

What MTU should I use for a GRE tunnel with BGP?

On a standard 1500-byte underlay, GRE over IPv4 adds 24 bytes, so use a tunnel MTU of 1476. Clamp TCP MSS to 1436 for IPv4 or 1416 for IPv6. If your underlay MTU is lower, reduce these values accordingly and confirm them with your provider.

Do I need my own ASN and IP block for a BGP tunnel?

Yes. You need an ASN and a prefix registered to you, with a matching RPKI ROA and IRR route objects. Without them, the provider can't verify ownership and your announcement will be filtered.

Why does my BGP session stay up but traffic stalls?

This is almost always an MTU or MSS problem. Small packets and BGP keepalives pass, but full-size TCP segments get dropped inside the tunnel. Set the tunnel MTU, clamp MSS on the tunnel interface, and test with DF-bit pings.

Own an ASN? Set up DDoS-protected BGP with Nixcon today.Learn more