hysteria/extras/outbounds/ob_direct_linux.go
2023-07-28 13:44:33 -07:00

57 lines
1.3 KiB
Go

package outbounds
import (
"errors"
"net"
"syscall"
)
// NewDirectOutboundBindToDevice creates a new directOutbound with the given mode,
// and binds to the given device. Only works on Linux.
func NewDirectOutboundBindToDevice(mode DirectOutboundMode, deviceName string) (PluggableOutbound, error) {
if err := verifyDeviceName(deviceName); err != nil {
return nil, err
}
d := &net.Dialer{
Timeout: defaultDialerTimeout,
Control: func(network, address string, c syscall.RawConn) error {
var errBind error
err := c.Control(func(fd uintptr) {
errBind = syscall.BindToDevice(int(fd), deviceName)
})
if err != nil {
return err
}
return errBind
},
}
return &directOutbound{
Mode: mode,
Dialer4: d,
Dialer6: d,
DeviceName: deviceName,
}, nil
}
func verifyDeviceName(deviceName string) error {
if deviceName == "" {
return errors.New("device name cannot be empty")
}
_, err := net.InterfaceByName(deviceName)
return err
}
func udpConnBindToDevice(conn *net.UDPConn, deviceName string) error {
sc, err := conn.SyscallConn()
if err != nil {
return err
}
var errBind error
err = sc.Control(func(fd uintptr) {
errBind = syscall.BindToDevice(int(fd), deviceName)
})
if err != nil {
return err
}
return errBind
}