Skip to content

Commit

Permalink
add mac routes
Browse files Browse the repository at this point in the history
  • Loading branch information
lsgrep committed Apr 14, 2024
1 parent 9031aca commit 8ebcafc
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/swgp-go
/swgp-go.exe
.idea
2 changes: 2 additions & 0 deletions cmd/swgp-go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ func main() {
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigCh
logger.Info("Received exit signal", zap.Stringer("signal", sig))
cleanupHook(&sc, logger)
cancel()
}()

initHook(&sc, logger)
if err = m.Start(ctx); err != nil {
logger.Fatal("Failed to start services",
zap.String("confPath", confPath),
Expand Down
135 changes: 135 additions & 0 deletions cmd/swgp-go/main_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
//go:build darwin

package main

import (
"errors"
"github.com/database64128/swgp-go/service"
"go.uber.org/zap"
"golang.org/x/net/route"
"net"
"os/exec"
"syscall"
"time"
)

func discoverGateway() (ip net.IP, err error) {
rib, err := route.FetchRIB(syscall.AF_INET, syscall.NET_RT_DUMP, 0)
if err != nil {
return nil, err
}

msgs, err := route.ParseRIB(syscall.NET_RT_DUMP, rib)
if err != nil {
return nil, err
}

for _, m := range msgs {
switch m := m.(type) {
case *route.RouteMessage:
var ip net.IP
switch sa := m.Addrs[syscall.RTAX_GATEWAY].(type) {
case *route.Inet4Addr:
ip = net.IPv4(sa.IP[0], sa.IP[1], sa.IP[2], sa.IP[3])
return ip, nil
case *route.Inet6Addr:
ip = make(net.IP, net.IPv6len)
copy(ip, sa.IP[:])
return ip, nil
}
}
}
return nil, errors.New("no ip found")
}

func executeCommands(logger *zap.Logger, commands []string) error {
for _, cmdStr := range commands {
cmd := exec.Command("bash", "-c", cmdStr)
// Run the command and capture its output.
output, err := cmd.CombinedOutput()
if err != nil {
return err
}
logger.Info("Command executed", zap.String("output", string(output)))
}
return nil
}

func addGatewayRoute(cfg *service.Config, logger *zap.Logger, gatewayIp net.IP, err error) {
for _, client := range cfg.Clients {
commands := []string{
"sudo route delete " + client.ProxyEndpointAddress.IP().String(),
"sudo route add " + client.ProxyEndpointAddress.IP().String() + "/32 " + gatewayIp.String(),
}
err = executeCommands(logger, commands)
if err != nil {
logger.Error("Failed to recreate route:", zap.Error(err))
}
}
}

func deleteGatewayRoute(cfg *service.Config, logger *zap.Logger) {
for _, client := range cfg.Clients {
err := executeCommands(logger, []string{"sudo route delete " + client.ProxyEndpointAddress.IP().String()})
if err != nil {
logger.Error("Failed to delete route:", zap.Error(err))
}
}
}

var macGateway = gatewayMonitor{}

type gatewayMonitor struct {
ip net.IP
logger *zap.Logger
cfg *service.Config
cancelled chan struct{}
}

func (g *gatewayMonitor) watch() {
for {
select {
case <-g.cancelled:
return
default:
ip, err := discoverGateway()
if err != nil {
g.logger.Error("Failed to get Gateway address:", zap.Error(err))
}
if !g.ip.Equal(ip) {
g.logger.Info("Gateway address changed, reconfiguring routes")
deleteGatewayRoute(g.cfg, g.logger)
addGatewayRoute(g.cfg, g.logger, ip, err)

// update ip
g.ip = ip
}
// sleep for 10 seconds
time.Sleep(10 * time.Second)

// show current gateway route
g.logger.Info("Current gateway route:" + ip.String())
}
}
}

// add route
func initHook(cfg *service.Config, logger *zap.Logger) {
gatewayIp, err := discoverGateway()
if err != nil {
logger.Fatal("Failed to get Gateway address:", zap.Error(err))
}
addGatewayRoute(cfg, logger, gatewayIp, err)
macGateway.ip = gatewayIp
macGateway.logger = logger
macGateway.cfg = cfg
macGateway.cancelled = make(chan struct{})
go macGateway.watch()
}

func cleanupHook(cfg *service.Config, logger *zap.Logger) {
deleteGatewayRoute(cfg, logger)

// cancel gateway monitor
close(macGateway.cancelled)
}
16 changes: 16 additions & 0 deletions cmd/swgp-go/main_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//go:build linux

package main

import (
"github.com/database64128/swgp-go/service"
"go.uber.org/zap"
)

func initHook(config service.Config, logger *zap.Logger) {
// NOOP
}

func cleanerHook(config service.Config, logger *zap.Logger) {
// NOOP
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.22.2
require (
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.22.0
golang.org/x/net v0.21.0
golang.org/x/sys v0.19.0
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down

0 comments on commit 8ebcafc

Please sign in to comment.