Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save paltaio-admin/7cc96cd55d61e46cf8641859f9a492f6 to your computer and use it in GitHub Desktop.

Select an option

Save paltaio-admin/7cc96cd55d61e46cf8641859f9a492f6 to your computer and use it in GitHub Desktop.
Pangolin Newt & OLM for MIPS OpenWrt (GL.iNet) - cross-compile, deploy, firewall config for WireGuard VPN tunnels

Newt on MIPS OpenWrt (GL.iNet)

Cross-compile and deploy newt to MIPS32 little-endian OpenWrt routers (e.g., Siflower SF19A28).

Build

# Clone
git clone https://github.com/fosrl/newt /tmp/newt
cd /tmp/newt

# Cross-compile for MIPS32 LE soft-float
GOOS=linux GOARCH=mipsle GOMIPS=softfloat CGO_ENABLED=0 \
  go build -ldflags="-s -w" -o newt_linux_mipsle .

With Nix:

nix develop --command bash -c \
  "GOOS=linux GOARCH=mipsle GOMIPS=softfloat CGO_ENABLED=0 go build -ldflags='-s -w' -o newt_linux_mipsle ."

Transfer

OpenWrt uses dropbear (no SFTP). Use legacy SCP:

scp -O newt_linux_mipsle root@openwrt-glinet:/usr/bin/newt
ssh root@openwrt-glinet "chmod +x /usr/bin/newt"

Verify:

ssh root@openwrt-glinet "/usr/bin/newt --help"

Configure

Create config file locally:

cat > /tmp/newt.config << 'EOF'
PANGOLIN_ENDPOINT="https://your-pangolin-server.com"
NEWT_ID="your-newt-id"
NEWT_SECRET="your-newt-secret"
EOF

Transfer:

ssh root@openwrt-glinet "mkdir -p /etc/newt"
cat /tmp/newt.config | ssh root@openwrt-glinet "cat > /etc/newt/config && chmod 600 /etc/newt/config"

Init Script

Create locally:

cat > /tmp/newt.init << 'EOF'
#!/bin/sh /etc/rc.common

START=99
STOP=10
USE_PROCD=1

start_service() {
    . /etc/newt/config

    procd_open_instance
    procd_set_param command /usr/bin/newt \
        --endpoint "$PANGOLIN_ENDPOINT" \
        --id "$NEWT_ID" \
        --secret "$NEWT_SECRET" \
        --log-level INFO
    procd_set_param respawn
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}
EOF

Transfer and enable:

cat /tmp/newt.init | ssh root@openwrt-glinet "cat > /etc/init.d/newt && chmod +x /etc/init.d/newt"
ssh root@openwrt-glinet "/etc/init.d/newt enable && /etc/init.d/newt start"

Verify

ssh root@openwrt-glinet "ps | grep newt"
ssh root@openwrt-glinet "logread | grep newt | tail -10"

Expected output:

Websocket connected
Tunnel connection to server established successfully!
Client connectivity setup. Ready to accept connections from clients!

Service Management

/etc/init.d/newt start
/etc/init.d/newt stop
/etc/init.d/newt restart
/etc/init.d/newt enable   # start at boot
/etc/init.d/newt disable  # disable at boot

Site-to-Site Routing (Optional)

If using newt as a subnet gateway with --accept-clients, use native mode to create a kernel interface:

procd_set_param command /usr/bin/newt \
    --endpoint "$PANGOLIN_ENDPOINT" \
    --id "$NEWT_ID" \
    --secret "$NEWT_SECRET" \
    --native \
    --log-level INFO

Enable IP forwarding:

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
echo "net.ipv4.conf.all.rp_filter=0" >> /etc/sysctl.conf
sysctl -p

See fosrl/pangolin#1370 for details on userspace vs native mode limitations.

Notes

  • Config stored at /.config/newt-client/config.json after first successful connection

OLM on MIPS OpenWrt (GL.iNet)

Cross-compile and deploy OLM to MIPS32 little-endian OpenWrt routers (e.g., Siflower SF19A28) as a system-wide VPN gateway.

Build

# Clone
git clone https://github.com/fosrl/olm /tmp/olm
cd /tmp/olm

# Cross-compile for MIPS32 LE soft-float
GOOS=linux GOARCH=mipsle GOMIPS=softfloat CGO_ENABLED=0 \
  go build -ldflags="-s -w" -o olm_linux_mipsle .

With Nix:

nix run nixpkgs#go -- build -ldflags="-s -w" -o olm_linux_mipsle \
  GOOS=linux GOARCH=mipsle GOMIPS=softfloat CGO_ENABLED=0 .

Transfer

OpenWrt uses dropbear (no SFTP). Use legacy SCP:

scp -O olm_linux_mipsle root@openwrt-glinet:/usr/bin/olm
ssh root@openwrt-glinet "chmod +x /usr/bin/olm"

Verify:

ssh root@openwrt-glinet "/usr/bin/olm --help"

Configure

Create config file locally:

cat > /tmp/olm.json << 'EOF'
{
  "endpoint": "https://your-pangolin-server.com",
  "id": "your-olm-id",
  "secret": "your-olm-secret",
  "mtu": 1280,
  "interface": "olm0",
  "logLevel": "INFO"
}
EOF

Transfer:

ssh root@openwrt-glinet "mkdir -p /root/.config/olm-client"
cat /tmp/olm.json | ssh root@openwrt-glinet "cat > /root/.config/olm-client/config.json && chmod 600 /root/.config/olm-client/config.json"

Init Script

Create locally:

cat > /tmp/olm.init << 'EOF'
#!/bin/sh /etc/rc.common

START=95
STOP=05
USE_PROCD=1

start_service() {
    local count=0
    while [ $count -lt 30 ]; do
        ip route | grep -q "default" && break
        sleep 1
        count=$((count + 1))
    done

    procd_open_instance
    procd_set_param command /usr/bin/olm
    procd_set_param env HOME=/root
    procd_set_param respawn
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}

stop_service() {
    ip link del olm0 2>/dev/null || true
}
EOF

Transfer and enable:

cat /tmp/olm.init | ssh root@openwrt-glinet "cat > /etc/init.d/olm && chmod +x /etc/init.d/olm"
ssh root@openwrt-glinet "/etc/init.d/olm enable && /etc/init.d/olm start"

Firewall

OLM creates a TUN interface olm0. To route LAN traffic through the tunnel:

ssh root@openwrt-glinet << 'EOF'
uci add firewall zone
uci set firewall.@zone[-1].name='pangolin'
uci set firewall.@zone[-1].input='REJECT'
uci set firewall.@zone[-1].output='ACCEPT'
uci set firewall.@zone[-1].forward='REJECT'
uci set firewall.@zone[-1].masq='1'
uci set firewall.@zone[-1].mtu_fix='1'
uci add_list firewall.@zone[-1].device='olm0'

uci add firewall forwarding
uci set firewall.@forwarding[-1].src='lan'
uci set firewall.@forwarding[-1].dest='pangolin'

uci add firewall forwarding
uci set firewall.@forwarding[-1].src='pangolin'
uci set firewall.@forwarding[-1].dest='lan'

uci commit firewall
/etc/init.d/firewall reload
EOF

Verify

ssh root@openwrt-glinet "ps | grep olm"
ssh root@openwrt-glinet "logread | grep olm | tail -10"

Expected output:

Olm version ...
Starting HTTP server on socket /var/run/olm.sock
Created shared UDP socket on port ...
WireGuard device created.

Test from a LAN device (laptop, phone) connected to the router's WiFi:

ping <pangolin-resource-ip>

Service Management

/etc/init.d/olm start
/etc/init.d/olm stop
/etc/init.d/olm restart
/etc/init.d/olm enable   # start at boot
/etc/init.d/olm disable  # disable at boot

Notes

  • OLM adds routes automatically based on Pangolin server config
  • Firewall binds directly to olm0 device (not network interface) because OLM creates TUN dynamically
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment