A Complete Guide to why Core Transit’s WireGuard IP Transit Service is so incredibly awesome for you lab

Bypassing CG-NAT with style – a detailed technical walkthrough


The Problem: CG-NAT Hell

If you’re reading this, you probably know the pain. Your ISP puts you behind Carrier-Grade NAT (CG-NAT), which means:

  • No port forwarding
  • No hosting servers at home
  • No running services accessible from the internet
  • Dynamic, shared IP addresses

I was stuck behind CG-NAT on my home internet connection and needed real, routable public IP addresses for my homelab. After researching options (VPS with reverse proxy, Cloudflare Tunnel, etc.), I discovered Core Transit – a service that provides actual public IPv4 and IPv6 blocks via WireGuard tunnel.

The Solution: Core Transit

Core Transit offers WireGuard-based IP transit. You get:

  • A dedicated public IPv4 block (I got a /28 = 14 usable IPs)
  • A public IPv6 block (I got a /60 = 16x /64 subnets)
  • Traffic routed through their infrastructure via encrypted WireGuard tunnel
  • Works through any NAT, including CG-NAT

This guide documents every step I took to get it working on a Linux gateway/router.


Prerequisites

Hardware

  • A Linux server/router with at least 2 network interfaces
  • One interface for WAN (internet connectivity)
  • One interface for your DMZ/public-facing network

Software

  • Linux with kernel 5.6+ (WireGuard built-in) or wireguard-tools
  • Open vSwitch (optional, for bridge management)
  • nftables or iptables for firewall
  • dnsmasq (optional, for DHCP on DMZ)

From Core Transit

After signing up, you’ll receive:

  • Your allocated IPv4 block (e.g., 203.0.113.176/28)
  • Your allocated IPv6 block (e.g., 2001:db8:abcd:1e0::/60)
  • Tunnel endpoint IP and port
  • Tunnel point-to-point addresses
  • Their WireGuard public key
  • Your WireGuard keypair (or generate your own)

Network Architecture

Here’s what we’re building:

                              INTERNET
                                  │
                    ┌─────────────┴─────────────┐
                    │      CORE TRANSIT POP     │
                    │    (Your tunnel endpoint) │
                    │                           │
                    │  Routes to you:           │
                    │  • YOUR_IPV4_BLOCK/28     │
                    │  • YOUR_IPV6_BLOCK/60     │
                    └─────────────┬─────────────┘
                                  │
                         WireGuard Tunnel
                        (ChaCha20-Poly1305)
                                  │
══════════════════════════════════╪════════════════════
           YOUR NETWORK           │
                                  │
                    ┌─────────────┴─────────────┐
                    │      YOUR ISP GATEWAY     │
                    │    (NAT / CG-NAT / etc)   │
                    └─────────────┬─────────────┘
                                  │
            ┌─────────────────────┴─────────────────────┐
            │              YOUR LINUX GATEWAY           │
            │                                           │
            │  ┌───────────┐                            │
            │  │  eth-wan  │ WAN interface (DHCP)       │
            │  │           │ Default route to ISP       │
            │  └─────┬─────┘                            │
            │        │                                  │
            │  ┌─────┴─────┐     ┌──────────────────┐   │
            │  │wg-transit │     │     br-dmz       │   │
            │  │           │     │  (OVS Bridge)    │   │
            │  │Tunnel IPs │     │                  │   │
            │  │           │     │ Public Gateway   │   │
            │  │           │     │ YOUR_BLOCK.177   │   │
            │  └───────────┘     └────────┬─────────┘   │
            │                             │             │
            │         Policy Routing      │             │
            │         (Table 100)         │             │
            │                   ┌─────────┘             │
            │                   │                       │
            │              ┌────┴────┐                  │
            │              │ eth-dmz │ Physical port    │
            │              └────┬────┘                  │
            └───────────────────│───────────────────────┘
                                │
                           DMZ Network
                                │
                    ┌───────────┴───────────┐
                    │                       │
             ┌──────┴──────┐         ┌──────┴──────┐
             │   Server    │         │   Server    │
             │  .178       │         │  .179       │
             └─────────────┘         └─────────────┘

Key Concepts

  1. WireGuard Tunnel: Encrypted connection to Core Transit carrying your public IP traffic
  2. Policy Routing: Traffic FROM your public IPs routes through the tunnel, not your normal ISP
  3. DMZ Bridge: Internal network where you assign public IPs to servers
  4. Firewall: Protect your gateway from the public internet

Step 1: Install WireGuard Tools

Ubuntu/Debian

apt update
apt install wireguard-tools

RHEL/CentOS/Rocky

dnf install wireguard-tools

Verify Installation

# Check if WireGuard kernel module is available
modprobe wireguard
lsmod | grep wireguard

# Check wg command exists
which wg
wg --version

What this does: Installs the userspace tools (wg, wg-quick) needed to configure WireGuard interfaces. Modern kernels (5.6+) have WireGuard built-in; older kernels may need the DKMS module.


Step 2: Generate WireGuard Keys (If Not Provided)

If Core Transit didn’t generate keys for you:

# Generate private key
wg genkey > /etc/wireguard/private.key
chmod 600 /etc/wireguard/private.key

# Derive public key from private key
cat /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key

# View your public key (send this to Core Transit)
cat /etc/wireguard/public.key

What this does: Creates a cryptographic keypair. The private key stays on your server (never share it!). The public key gets registered with Core Transit so they can authenticate your tunnel.


Step 3: Create WireGuard Configuration

Create the configuration file:

nano /etc/wireguard/wg-coretransit.conf

Paste the following (replace placeholders with your actual values):

# Core Transit WireGuard Tunnel Configuration
# Replace all YOUR_* values with actual values from Core Transit

[Interface]
# Your private key (keep this secret!)
PrivateKey = YOUR_PRIVATE_KEY_HERE

# Tunnel point-to-point addresses (provided by Core Transit)
# These are the IPs assigned to YOUR end of the tunnel
Address = YOUR_TUNNEL_IPV4/31, YOUR_TUNNEL_IPV6/64

# MTU - Start with 1420, we may need to lower this later
MTU = 1420

# Use a separate routing table for policy routing
Table = 100

# Policy routing rules - traffic FROM your public block uses table 100
PostUp = ip rule add from YOUR_IPV4_BLOCK/28 table 100 priority 5
PostUp = ip -6 rule add from YOUR_IPV6_BLOCK/60 table 100 priority 5

PostDown = ip rule del from YOUR_IPV4_BLOCK/28 table 100 priority 5
PostDown = ip -6 rule del from YOUR_IPV6_BLOCK/60 table 100 priority 5

[Peer]
# Core Transit's public key (provided by them)
PublicKey = CORETRANSIT_PUBLIC_KEY_HERE

# Core Transit endpoint (IP:port provided by them)
Endpoint = CORETRANSIT_ENDPOINT_IP:PORT

# Route ALL traffic through tunnel (for table 100 only)
AllowedIPs = 0.0.0.0/0, ::/0

# Keep tunnel alive through NAT
PersistentKeepalive = 25

Example with Placeholder Values

[Interface]
PrivateKey = aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890abcdefg=
Address = 203.0.113.253/31, 2001:db8:1000:23::2/64
MTU = 1420
Table = 100

PostUp = ip rule add from 203.0.113.176/28 table 100 priority 5
PostUp = ip -6 rule add from 2001:db8:abcd:1e0::/60 table 100 priority 5
PostDown = ip rule del from 203.0.113.176/28 table 100 priority 5
PostDown = ip -6 rule del from 2001:db8:abcd:1e0::/60 table 100 priority 5

[Peer]
PublicKey = XyZ0987654321AbCdEfGhIjKlMnOpQrStUvWxYz1234=
Endpoint = 198.51.100.1:10305
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

What this does:

  • PrivateKey: Authenticates your side of the tunnel
  • Address: IPs assigned to the tunnel interface itself (point-to-point link)
  • MTU: Maximum packet size (more on this later)
  • Table = 100: Routes learned from this tunnel go into routing table 100, not main
  • PostUp/PostDown: Policy routing rules that send traffic FROM your public IPs through the tunnel
  • PublicKey: Core Transit’s identity
  • Endpoint: Where to send encrypted packets
  • AllowedIPs = 0.0.0.0/0, ::/0: Accept any destination (full tunnel for table 100)
  • PersistentKeepalive: Keeps NAT mappings alive

Set proper permissions:

chmod 600 /etc/wireguard/wg-coretransit.conf

Step 4: Enable IP Forwarding

Your gateway needs to forward packets between interfaces:

# Enable immediately
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

# Make persistent across reboots
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding=1" >> /etc/sysctl.conf

What this does: Allows your Linux box to act as a router, forwarding packets between the tunnel interface, DMZ interface, and WAN interface.


Step 5: Bring Up the WireGuard Tunnel

# Start the tunnel
wg-quick up wg-coretransit

# Verify it's running
wg show wg-coretransit

Expected output:

interface: wg-coretransit
  public key: YOUR_PUBLIC_KEY
  private key: (hidden)
  listening port: 51820

peer: CORETRANSIT_PUBLIC_KEY
  endpoint: 198.51.100.1:10305
  allowed ips: 0.0.0.0/0, ::/0
  latest handshake: 5 seconds ago    <-- THIS IS THE KEY LINE
  transfer: 1.23 MiB received, 456.78 KiB sent
  persistent keepalive: every 25 seconds

Success indicator: You should see “latest handshake: X seconds ago”. If this never appears, the tunnel isn’t establishing.

Test Tunnel Connectivity

# Ping Core Transit's tunnel IP (their side of the point-to-point link)
# This IP is typically YOUR_TUNNEL_IP - 1 or as provided by Core Transit
ping YOUR_CORETRANSIT_TUNNEL_PEER_IP

# Example:
ping 203.0.113.252

If this works, your tunnel is up!


Step 6: Create the DMZ Bridge (Optional but Recommended)

Using Open vSwitch to create a bridge for your public-facing network:

# Install OVS if not present
apt install openvswitch-switch

# Create the bridge
ovs-vsctl add-br br-dmz

# Add your physical DMZ interface to the bridge
# Replace eth-dmz with your actual interface name
ovs-vsctl add-port br-dmz eth-dmz

# Bring up interfaces
ip link set eth-dmz up
ip link set br-dmz up

Alternative without OVS (using standard Linux bridge):

# Create bridge
ip link add br-dmz type bridge

# Add physical interface
ip link set eth-dmz master br-dmz

# Bring up
ip link set eth-dmz up
ip link set br-dmz up

Step 7: Assign Public IPs to the DMZ Bridge

The bridge interface becomes your gateway for the public IP block:

# Assign the first usable IP as the gateway
# For a /28 block, .176 is network, .177 is first usable, .191 is broadcast
ip addr add YOUR_GATEWAY_IP/28 dev br-dmz
ip addr add YOUR_IPV6_GATEWAY/64 dev br-dmz

# Example:
ip addr add 203.0.113.177/28 dev br-dmz
ip addr add 2001:db8:abcd:1e0::1/64 dev br-dmz

Important: Set the MTU to match your WireGuard tunnel:

ip link set br-dmz mtu 1420

Step 8: Configure Policy Routing

This is the magic that makes it work. Traffic FROM your public IPs must route through the tunnel, not your regular ISP.

Verify Policy Routing Rules

The WireGuard PostUp commands should have created these:

ip rule show

Expected output:

0:      from all lookup local
5:      from 203.0.113.176/28 lookup 100       <-- Your IPv4 block
10:     from all lookup main
...
ip -6 rule show

Expected:

0:      from all lookup local
5:      from 2001:db8:abcd:1e0::/60 lookup 100  <-- Your IPv6 block
...

Add Local Routes to Table 100

Traffic within your public block should stay local, not go through the tunnel:

# Local DMZ network (so hosts can talk to each other)
ip route add YOUR_IPV4_BLOCK/28 dev br-dmz table 100
ip -6 route add YOUR_IPV6_BLOCK/64 dev br-dmz table 100

# Tunnel point-to-point network
ip route add YOUR_TUNNEL_SUBNET/31 dev wg-coretransit table 100

# Example:
ip route add 203.0.113.176/28 dev br-dmz table 100
ip route add 203.0.113.252/31 dev wg-coretransit table 100
ip -6 route add 2001:db8:abcd:1e0::/64 dev br-dmz table 100

Verify Routing Table 100

ip route show table 100

Expected:

default dev wg-coretransit scope link           <-- All other traffic via tunnel
203.0.113.176/28 dev br-dmz scope link          <-- Local DMZ stays local
203.0.113.252/31 dev wg-coretransit scope link  <-- Tunnel network

What this does: When a packet has a source IP in your public block (203.0.113.176/28), the kernel consults table 100 instead of the main routing table. Table 100 sends everything through the WireGuard tunnel, except local DMZ traffic.


Step 9: Test Public IP Routing

This is the moment of truth:

# Test outbound - does traffic from your public IP reach the internet?
ping -I YOUR_GATEWAY_IP 8.8.8.8
ping -I 203.0.113.177 8.8.8.8

# Test IPv6
ping6 -I YOUR_IPV6_GATEWAY 2001:4860:4860::8888
ping6 -I 2001:db8:abcd:1e0::1 2001:4860:4860::8888

# Verify your public IP is what you expect
curl -4 --interface YOUR_GATEWAY_IP ifconfig.me
curl -4 --interface 203.0.113.177 ifconfig.me
# Should return: 203.0.113.177 (or similar from your block)

If this works, congratulations! Your public IPs are routing through Core Transit.


Step 10: The MTU Problem (Critical!)

Symptoms of MTU Issues

After initial setup, you might experience:

  • Pings work, but web pages hang or load very slowly
  • SSH connects but freezes when displaying large output
  • Small transfers work, large transfers stall
  • HTTPS sites fail while HTTP works

The Cause

WireGuard adds ~60 bytes of overhead to each packet. If your underlying path has a reduced MTU (common with CG-NAT, PPPoE, mobile networks), large packets get silently dropped.

Diagnose the MTU

Find the maximum working packet size:

# Start with a reasonable size and decrease until it works
# The -M do flag prevents fragmentation

ping -c 1 -M do -s 1400 YOUR_CORETRANSIT_TUNNEL_PEER_IP  # Probably fails
ping -c 1 -M do -s 1350 YOUR_CORETRANSIT_TUNNEL_PEER_IP  # Maybe works
ping -c 1 -M do -s 1300 YOUR_CORETRANSIT_TUNNEL_PEER_IP  # Should work

Example diagnosis session:

$ ping -c 1 -M do -s 1400 203.0.113.252
PING 203.0.113.252 (203.0.113.252) 1400(1428) bytes of data.
--- 203.0.113.252 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss   # <-- TOO BIG

$ ping -c 1 -M do -s 1300 203.0.113.252
PING 203.0.113.252 (203.0.113.252) 1300(1328) bytes of data.
1328 bytes from 203.0.113.252: icmp_seq=1 ttl=64 time=25.3 ms  # <-- WORKS

Calculate Correct MTU

The WireGuard MTU should be:

WG_MTU = Maximum_Working_Payload + 28 - 60

Where:

  • Maximum_Working_Payload = largest -s value that works
  • +28 = IP header (20) + ICMP header (8) that ping adds
  • -60 = WireGuard overhead

Example: If -s 1300 works:

  • Working packet = 1300 + 28 = 1328 bytes
  • WireGuard MTU = 1328 – 60 = 1268 → round to 1280 (safe) or 1320 (aggressive)

Apply MTU Fix

Edit your WireGuard config:

nano /etc/wireguard/wg-coretransit.conf

Change:

MTU = 1420

To:

MTU = 1320

Restart the tunnel:

wg-quick down wg-coretransit
wg-quick up wg-coretransit

Also update the DMZ bridge MTU:

ip link set br-dmz mtu 1320

Add MSS Clamping (Belt and Suspenders)

To prevent MTU issues with TCP, clamp the MSS (Maximum Segment Size):

# Using nftables
nft add table inet mangle
nft add chain inet mangle FORWARD '{ type filter hook forward priority -150; policy accept; }'
nft add rule inet mangle FORWARD oifname "wg-coretransit" tcp flags syn tcp option maxseg size set 1280
nft add rule inet mangle FORWARD iifname "wg-coretransit" tcp flags syn tcp option maxseg size set 1280

What this does: Forces TCP connections through the tunnel to negotiate a smaller maximum segment size, preventing fragmentation issues.


Step 11: Configure Firewall

Your gateway is now reachable from the public internet. Lock it down.

Basic nftables Rules

# Block inbound connections from the tunnel to your gateway
nft add rule inet filter input iifname "wg-coretransit" ct state new drop

# Block inbound connections from DMZ to your gateway (except DHCP/DNS)
nft add rule inet filter input iifname "br-dmz" udp dport { 67, 68 } accept
nft add rule inet filter input iifname "br-dmz" udp dport 53 accept
nft add rule inet filter input iifname "br-dmz" icmp type echo-request accept
nft add rule inet filter input iifname "br-dmz" ct state new drop

# Prevent DMZ from reaching your private LAN
nft add rule inet filter forward iifname "br-dmz" oifname "eth-lan" drop
nft add rule inet filter forward iifname "wg-coretransit" oifname "eth-lan" drop

What this does:

  • Blocks the public internet from accessing services on your gateway
  • Allows DHCP and DNS from DMZ hosts
  • Prevents DMZ hosts from accessing your private LAN

Step 12: DHCP Server for DMZ (Optional)

If you want to dynamically assign public IPs to DMZ hosts:

# Install dnsmasq
apt install dnsmasq

# Create config
nano /etc/dnsmasq.d/br-dmz.conf

Content:

# DMZ DHCP Configuration
interface=br-dmz
bind-dynamic

# DHCP range - only offer a few IPs from your block
# Reserve most for static assignment
dhcp-range=YOUR_DHCP_START,YOUR_DHCP_END,255.255.255.240,12h

# Gateway (your br-dmz IP)
dhcp-option=br-dmz,3,YOUR_GATEWAY_IP

# DNS servers
dhcp-option=br-dmz,6,1.1.1.1,8.8.8.8

# Example:
# dhcp-range=203.0.113.189,203.0.113.190,255.255.255.240,12h
# dhcp-option=br-dmz,3,203.0.113.177

Restart dnsmasq:

systemctl restart dnsmasq

Step 13: Make It Persistent (Survive Reboots)

Create Startup Script

nano /usr/local/bin/coretransit-startup.sh

Content:

#!/bin/bash
# Core Transit Startup Script

set -e

echo "Starting Core Transit configuration..."

# 1. Enable IP forwarding
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

# 2. Ensure DMZ bridge exists
if ! ip link show br-dmz &>/dev/null; then
    # For OVS:
    ovs-vsctl add-br br-dmz
    ovs-vsctl add-port br-dmz eth-dmz
    # Or for standard bridge:
    # ip link add br-dmz type bridge
    # ip link set eth-dmz master br-dmz
fi

# 3. Bring up interfaces
ip link set eth-dmz up
ip link set br-dmz up

# 4. Assign IPs to DMZ bridge
ip addr add YOUR_GATEWAY_IP/28 dev br-dmz 2>/dev/null || true
ip addr add YOUR_IPV6_GATEWAY/64 dev br-dmz 2>/dev/null || true

# 5. Start WireGuard tunnel
if ! ip link show wg-coretransit &>/dev/null; then
    wg-quick up wg-coretransit
fi

# 6. Add local routes to table 100
ip route add YOUR_IPV4_BLOCK/28 dev br-dmz table 100 2>/dev/null || true
ip route add YOUR_TUNNEL_SUBNET/31 dev wg-coretransit table 100 2>/dev/null || true
ip -6 route add YOUR_IPV6_SUBNET/64 dev br-dmz table 100 2>/dev/null || true

# 7. Set MTU on DMZ bridge
ip link set br-dmz mtu 1320

# 8. Apply firewall rules
nft add rule inet filter input iifname "wg-coretransit" ct state new drop 2>/dev/null || true
nft add rule inet filter input iifname "br-dmz" ct state new drop 2>/dev/null || true

# 9. MSS clamping
nft add table inet mangle 2>/dev/null || true
nft add chain inet mangle FORWARD '{ type filter hook forward priority -150; policy accept; }' 2>/dev/null || true
nft add rule inet mangle FORWARD oifname "wg-coretransit" tcp flags syn tcp option maxseg size set 1280 2>/dev/null || true
nft add rule inet mangle FORWARD iifname "wg-coretransit" tcp flags syn tcp option maxseg size set 1280 2>/dev/null || true

# 10. Verify tunnel
if ping -c 1 -W 5 YOUR_CORETRANSIT_TUNNEL_PEER_IP > /dev/null 2>&1; then
    echo "SUCCESS: Core Transit tunnel is UP"
else
    echo "WARNING: Tunnel may not be established yet"
fi

echo "Core Transit startup complete!"

Make it executable:

chmod +x /usr/local/bin/coretransit-startup.sh

Create Systemd Service

nano /etc/systemd/system/coretransit.service

Content:

[Unit]
Description=Core Transit WireGuard IP Transit
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/coretransit-startup.sh

[Install]
WantedBy=multi-user.target

Enable the service:

systemctl daemon-reload
systemctl enable coretransit.service

Step 14: Verification Checklist

Run through these tests to confirm everything works:

# 1. WireGuard tunnel status
wg show wg-coretransit
# Look for "latest handshake" timestamp

# 2. Ping tunnel peer
ping -c 3 YOUR_CORETRANSIT_TUNNEL_PEER_IP

# 3. Test outbound IPv4 via public IP
ping -c 3 -I YOUR_GATEWAY_IP 8.8.8.8

# 4. Test outbound IPv6 via public IP
ping6 -c 3 -I YOUR_IPV6_GATEWAY 2001:4860:4860::8888

# 5. Verify public IP
curl -4 --interface YOUR_GATEWAY_IP ifconfig.me
# Should return an IP from your allocated block

# 6. Check policy routing rules
ip rule show | grep YOUR_IPV4_BLOCK

# 7. Check routing table 100
ip route show table 100

# 8. Test from a DMZ host (if available)
# From a server with IP in your public block:
ping 8.8.8.8
curl ifconfig.me
# Should show public IP from your block

Troubleshooting Guide

Tunnel Won’t Establish (No Handshake)

Symptoms: wg show never shows “latest handshake”

Checks:

# Is UDP traffic reaching Core Transit?
nc -zuv CORETRANSIT_ENDPOINT_IP PORT

# Check for firewall blocking outbound UDP
iptables -L -n | grep DROP
nft list ruleset | grep drop

Common causes:

  • Firewall blocking outbound UDP
  • Wrong endpoint IP/port
  • Wrong public key
  • Core Transit hasn’t registered your public key yet

Tunnel Up But No Traffic

Symptoms: Handshake works, but ping -I YOUR_IP 8.8.8.8 fails

Checks:

# Verify policy routing rule exists
ip rule show
# Must see: "from YOUR_BLOCK lookup 100"

# Verify table 100 has default route
ip route show table 100
# Must see: "default dev wg-coretransit"

# Check for conflicting default routes
ip route show default
# Should NOT see your public gateway IP here

Common causes:

  • Policy routing rules not created
  • Table 100 missing default route
  • Another interface stealing the default route

Slow Speeds / Stalling Transfers

Symptoms: Small pings work, large transfers hang

Solution: MTU problem. See Step 10.

Works Initially, Breaks After Time

Symptoms: Everything works, then stops after minutes/hours

Common causes:

  • DHCP on management interface adding rogue default route
  • NAT timeout on ISP (increase PersistentKeepalive)

Fix for rogue routes:

# Create a cron job to remove bad routes
crontab -e

# Add:
* * * * * ip route del default via YOUR_LAN_GATEWAY dev eth-lan 2>/dev/null || true

Final Network Diagram

After setup, your traffic flows look like this:

DMZ Host (203.0.113.178)
         │
         │ Packet: src=203.0.113.178 dst=8.8.8.8
         │
         ▼
    ┌─────────┐
    │ br-dmz  │ Gateway receives packet
    └────┬────┘
         │
         │ Policy routing: "src 203.0.113.0/28 → table 100"
         │ Table 100: "default → wg-coretransit"
         │
         ▼
  ┌──────────────┐
  │wg-coretransit│ WireGuard encrypts packet
  └──────┬───────┘
         │
         │ Encrypted WG packet: src=YOUR_WAN_IP dst=CORETRANSIT_ENDPOINT
         │
         ▼
    ┌─────────┐
    │ eth-wan │ Sent via normal ISP default route
    └────┬────┘
         │
         ▼
    ISP (CG-NAT)
         │
         ▼
    INTERNET
         │
         ▼
   CORE TRANSIT
         │
         │ Decrypts, routes to internet as 203.0.113.178
         │
         ▼
      8.8.8.8

Conclusion

That’s it! You now have real, routable public IP addresses at home, tunneled through Core Transit’s WireGuard service. Your servers can:

  • Accept inbound connections from the internet
  • Host websites, game servers, mail servers, etc.
  • Use static public IPs that you control
  • Work through any NAT, including CG-NAT

The key pieces are:

  1. WireGuard tunnel for encrypted transport
  2. Policy routing to direct public IP traffic through the tunnel
  3. Proper MTU to avoid packet fragmentation issues
  4. Firewall to protect your gateway

Core Transit has been rock solid for me. The tunnel reconnects automatically, speeds are good, and having real public IPs again feels like getting my internet freedom back.


Quick Reference Card

ItemValue
WireGuard config/etc/wireguard/wg-coretransit.conf
Startup script/usr/local/bin/coretransit-startup.sh
Systemd service/etc/systemd/system/coretransit.service
Routing table100
Policy rule priority5
Recommended MTU1320 (adjust based on testing)
MSS clamp value1280

Essential Commands

# Tunnel status
wg show wg-coretransit

# Restart tunnel
wg-quick down wg-coretransit && wg-quick up wg-coretransit

# Check policy routing
ip rule show
ip route show table 100

# Test public IP
curl -4 --interface YOUR_GATEWAY_IP ifconfig.me

Questions? Issues? Drop a comment below or reach out. Happy tunneling!

Aliens? Any thoughts?

This site uses Akismet to reduce spam. Learn how your comment data is processed.