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.
43 lines
895 B
Go
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
|
|
}
|