mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-15 20:13:59 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5622d2fe05 | ||
|
|
dda0fa2bde |
@@ -125,7 +125,8 @@ func (t *Handler) Start() error {
|
||||
errors.LogInfo(context.Background(), "[tun] falied to set interface > iface == nil")
|
||||
return errors.New("iface not found")
|
||||
}
|
||||
return c.Control(func(fd uintptr) {
|
||||
var controlErr, sockErr error
|
||||
controlErr = c.Control(func(fd uintptr) {
|
||||
addrPort, _ := netip.ParseAddrPort(address)
|
||||
// skip loopback
|
||||
if addrPort.Addr().IsLoopback() || strings.HasPrefix(strings.ToLower(address), "localhost:") {
|
||||
@@ -133,9 +134,13 @@ func (t *Handler) Start() error {
|
||||
}
|
||||
err := setinterface(network, address, fd, iface)
|
||||
if err != nil {
|
||||
errors.LogInfoInner(context.Background(), err, "[tun] falied to set interface")
|
||||
sockErr = errors.New("[tun] falied to set interface").Base(err)
|
||||
}
|
||||
})
|
||||
if sockErr != nil {
|
||||
return sockErr
|
||||
}
|
||||
return controlErr
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -28,3 +28,22 @@ func (v *SocketConfig) ParseTFOValue() int {
|
||||
}
|
||||
return tfo
|
||||
}
|
||||
|
||||
// Dial should fail on bind errors, return this to indicate such errors.
|
||||
type BindError struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e *BindError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
func (e *BindError) Error() string {
|
||||
return "failed to bind to interface: " + e.err.Error()
|
||||
}
|
||||
|
||||
func NewBindError(err error) *BindError {
|
||||
return &BindError{
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,15 +136,15 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||
if config.Interface != "" {
|
||||
iface, err := net.InterfaceByName(config.Interface)
|
||||
if err != nil {
|
||||
return errors.New("failed to get interface ", config.Interface).Base(err)
|
||||
return NewBindError(errors.New("failed to get interface ", config.Interface).Base(err))
|
||||
}
|
||||
if network == "tcp6" || network == "udp6" {
|
||||
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil {
|
||||
return errors.New("failed to set IPV6_BOUND_IF").Base(err)
|
||||
return NewBindError(errors.New("failed to set IPV6_BOUND_IF").Base(err))
|
||||
}
|
||||
} else {
|
||||
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil {
|
||||
return errors.New("failed to set IP_BOUND_IF").Base(err)
|
||||
return NewBindError(errors.New("failed to set IP_BOUND_IF").Base(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||
|
||||
if config.Interface != "" {
|
||||
if err := syscall.BindToDevice(int(fd), config.Interface); err != nil {
|
||||
return errors.New("failed to set Interface").Base(err)
|
||||
return NewBindError(errors.New("failed to set Interface").Base(err))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||
if config.Interface != "" {
|
||||
inf, err := net.InterfaceByName(config.Interface)
|
||||
if err != nil {
|
||||
return errors.New("failed to find the interface").Base(err)
|
||||
return NewBindError(errors.New("failed to find the interface").Base(err))
|
||||
}
|
||||
// easy way to check if the address is ipv4
|
||||
isV4 := strings.Contains(address, ".")
|
||||
@@ -47,20 +47,20 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
||||
binary.BigEndian.PutUint32(bytes[:], uint32(inf.Index))
|
||||
idx := *(*uint32)(unsafe.Pointer(&bytes[0]))
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, IP_UNICAST_IF, int(idx)); err != nil {
|
||||
return errors.New("failed to set IP_UNICAST_IF").Base(err)
|
||||
return NewBindError(errors.New("failed to set IP_UNICAST_IF").Base(err))
|
||||
}
|
||||
if ip := net.ParseIP(host); ip != nil && ip.IsMulticast() && isUDPSocket(network) {
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IP, syscall.IP_MULTICAST_IF, int(idx)); err != nil {
|
||||
return errors.New("failed to set IP_MULTICAST_IF").Base(err)
|
||||
return NewBindError(errors.New("failed to set IP_MULTICAST_IF").Base(err))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, IPV6_UNICAST_IF, inf.Index); err != nil {
|
||||
return errors.New("failed to set IPV6_UNICAST_IF").Base(err)
|
||||
return NewBindError(errors.New("failed to set IPV6_UNICAST_IF").Base(err))
|
||||
}
|
||||
if ip := net.ParseIP(host); ip != nil && ip.IsMulticast() && isUDPSocket(network) {
|
||||
if err := syscall.SetsockoptInt(syscall.Handle(fd), syscall.IPPROTO_IPV6, syscall.IPV6_MULTICAST_IF, inf.Index); err != nil {
|
||||
return errors.New("failed to set IPV6_MULTICAST_IF").Base(err)
|
||||
return NewBindError(errors.New("failed to set IPV6_MULTICAST_IF").Base(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,19 +68,27 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
|
||||
}
|
||||
}
|
||||
var lc net.ListenConfig
|
||||
lc.Control = func(network, address string, c syscall.RawConn) error {
|
||||
for _, ctl := range Controllers {
|
||||
if err := ctl(network, address, c); err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to apply external controller")
|
||||
}
|
||||
}
|
||||
return c.Control(func(fd uintptr) {
|
||||
if sockopt != nil {
|
||||
if err := applyOutboundSocketOptions(network, destAddr.String(), fd, sockopt); err != nil {
|
||||
errors.LogInfo(ctx, err, "failed to apply socket options")
|
||||
if sockopt != nil || len(Controllers) > 0 {
|
||||
lc.Control = func(network, address string, c syscall.RawConn) error {
|
||||
for _, ctl := range Controllers {
|
||||
if err := ctl(network, address, c); err != nil {
|
||||
return errors.New("failed to apply external controller").Base(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
if sockopt != nil {
|
||||
var sockErr, controlErr error
|
||||
controlErr = c.Control(func(fd uintptr) {
|
||||
if sockErr = applyOutboundSocketOptions(network, destAddr.String(), fd, sockopt); sockErr != nil {
|
||||
errors.LogInfoInner(ctx, sockErr, "failed to apply socket options")
|
||||
}
|
||||
})
|
||||
if _, ok := sockErr.(*BindError); ok {
|
||||
return sockErr
|
||||
}
|
||||
return controlErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
packetConn, err := lc.ListenPacket(ctx, srcAddr.Network(), srcAddr.String())
|
||||
if err != nil {
|
||||
@@ -128,16 +136,22 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne
|
||||
dialer.Control = func(network, address string, c syscall.RawConn) error {
|
||||
for _, ctl := range Controllers {
|
||||
if err := ctl(network, address, c); err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to apply external controller")
|
||||
return errors.New("failed to apply external controller").Base(err)
|
||||
}
|
||||
}
|
||||
return c.Control(func(fd uintptr) {
|
||||
if sockopt != nil {
|
||||
if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to apply socket options")
|
||||
if sockopt != nil {
|
||||
var sockErr, controlErr error
|
||||
controlErr = c.Control(func(fd uintptr) {
|
||||
if sockErr = applyOutboundSocketOptions(network, address, fd, sockopt); sockErr != nil {
|
||||
errors.LogInfoInner(ctx, sockErr, "failed to apply socket options")
|
||||
}
|
||||
})
|
||||
if _, ok := sockErr.(*BindError); ok {
|
||||
return sockErr
|
||||
}
|
||||
})
|
||||
return controlErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user