Files
ihasvpn/internal/netcfg/egress_linux.go
T
jcoffey 6c006e1d4d WireGuard server with an embedded admin console
Go backend that drives kernel WireGuard over netlink (wireguard-go as the
fallback), nftables NAT with MSS clamping, forwarding and buffer sysctls,
SQLite for peers, users, sessions, traffic history and the audit log.

React console: dashboard with live rates and usage history, peer management
with QR codes and .conf downloads, disconnect, session reset, key rotation,
expiry, client-supplied keys, settings, users with admin and viewer roles,
two-factor authentication with recovery codes, audit log.

Docker image on Alpine with compose files for bridged and host networking,
CI and GHCR publish workflows, performance notes.
2026-09-12 19:56:08 -07:00

43 lines
895 B
Go

//go:build linux
package netcfg
import (
"errors"
"net"
"github.com/vishvananda/netlink"
)
// DefaultEgress returns the interface the default IPv4 route leaves through.
// Masquerading on exactly that interface (rather than "anything that is not
// wg0") keeps the NAT rule from touching docker-internal traffic.
func DefaultEgress() (string, error) {
routes, err := netlink.RouteList(nil, netlink.FAMILY_V4)
if err != nil {
return "", err
}
for _, r := range routes {
if r.Dst == nil || (r.Dst.IP.Equal(net.IPv4zero) && isZeroMask(r.Dst.Mask)) {
if r.LinkIndex == 0 {
continue
}
link, err := netlink.LinkByIndex(r.LinkIndex)
if err != nil {
return "", err
}
return link.Attrs().Name, nil
}
}
return "", errors.New("no default route")
}
func isZeroMask(m net.IPMask) bool {
for _, b := range m {
if b != 0 {
return false
}
}
return true
}