Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 46 additions & 8 deletions glutton.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strconv"
"strings"
"sync"
"syscall"
"time"

"github.com/mushorg/glutton/connection"
Expand All @@ -38,6 +39,7 @@ type Glutton struct {
ctx context.Context
cancel context.CancelFunc
publicAddrs []net.IP
iptablesChan chan string // channel to communicate with the IP Table routine
}

//go:embed config/rules.yaml
Expand Down Expand Up @@ -70,6 +72,7 @@ func New(ctx context.Context) (*Glutton, error) {
tcpProtocolHandlers: make(map[string]protocols.TCPHandlerFunc),
udpProtocolHandlers: make(map[string]protocols.UDPHandlerFunc),
connTable: connection.New(),
iptablesChan: make(chan string),
}
g.ctx, g.cancel = context.WithCancel(ctx)

Expand Down Expand Up @@ -251,6 +254,20 @@ func (g *Glutton) Start() error {
return err
}

go g.manageIptables()

uid := syscall.Getuid() // get the real UID (0 in this case which corresponds to root)
fmt.Print("UID before dropping : ", uid, "\n")

if uid == 0 {
if err := dropPrivileges(); err != nil {
return err
}
}

uid2 := syscall.Getuid()
fmt.Print("UID after dropping : ", uid2, "\n")

wg := &sync.WaitGroup{}

wg.Add(1)
Expand All @@ -262,6 +279,34 @@ func (g *Glutton) Start() error {
return nil
}

// Separate function for IPTable management. (Runs with root privileges)
func (g *Glutton) manageIptables() {
uid3 := syscall.Getuid()
fmt.Print("UID in IPTable routine : ", uid3, "\n")
for request := range g.iptablesChan {
if request == "flush" {
if err := flushTProxyIPTables(viper.GetString("interface"), g.publicAddrs[0].String(), "tcp", uint32(g.Server.tcpPort), uint32(viper.GetInt("ports.ssh"))); err != nil {
g.Logger.Error("Failed to flush TCP iptables", producer.ErrAttr(err))
}
if err := flushTProxyIPTables(viper.GetString("interface"), g.publicAddrs[0].String(), "udp", uint32(g.Server.udpPort), uint32(viper.GetInt("ports.ssh"))); err != nil {
g.Logger.Error("Failed to flush UDP iptables", producer.ErrAttr(err))
}
}
}
}

// Change the user and group to 'nobody' (UID 65534, GID 65534)
func dropPrivileges() error {
if err := syscall.Setgid(65534); err != nil {
return fmt.Errorf("failed to set group ID: %v", err)
}
if err := syscall.Setuid(65534); err != nil {
return fmt.Errorf("failed to set user ID: %v", err)
}

return nil
}

func (g *Glutton) makeID() error {
filePath := filepath.Join(viper.GetString("var-dir"), "glutton.id")
if err := os.MkdirAll(viper.GetString("var-dir"), 0744); err != nil {
Expand Down Expand Up @@ -356,14 +401,7 @@ func (g *Glutton) ProduceUDP(handler string, srcAddr, dstAddr *net.UDPAddr, md c
func (g *Glutton) Shutdown() {
g.cancel() // close all connection

g.Logger.Info("Flushing TCP iptables")
if err := flushTProxyIPTables(viper.GetString("interface"), g.publicAddrs[0].String(), "tcp", uint32(g.Server.tcpPort), uint32(viper.GetInt("ports.ssh"))); err != nil {
g.Logger.Error("Failed to drop tcp iptables", producer.ErrAttr(err))
}
g.Logger.Info("Flushing UDP iptables")
if err := flushTProxyIPTables(viper.GetString("interface"), g.publicAddrs[0].String(), "udp", uint32(g.Server.udpPort), uint32(viper.GetInt("ports.ssh"))); err != nil {
g.Logger.Error("Failed to drop udp iptables", producer.ErrAttr(err))
}
g.iptablesChan <- "flush"

g.Logger.Info("All done")
}
Expand Down