mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-07-06 03:38:47 +00:00
TUN inbound: Refine gateway and autoSystemRoutingTable on Linux (#6398)
https://github.com/XTLS/Xray-core/pull/6398#issuecomment-4880261591
This commit is contained in:
+5
-5
@@ -14,11 +14,11 @@ Plainly enabling it in the config probably will result nothing, or lock your rou
|
|||||||
|
|
||||||
## DETAILS
|
## DETAILS
|
||||||
|
|
||||||
Current implementation does not contain options to configure network level addresses, routing or rules.
|
By default, enabling the feature will only bring the tun interface up. \
|
||||||
Enabling the feature will result only tun interface up, and that's it. \
|
When configured explicitly, Windows and Linux can also apply interface addresses from `gateway` and on-link routes from `autoSystemRoutingTable`.
|
||||||
This is explicit decision, significantly simplifying implementation, and allowing any number of custom configurations, consumers could come up with. Network interface is OS level entity, and OS is what should manage it. \
|
Linux does not configure system DNS from the `dns` field; system DNS remains managed by the OS or distribution-specific network services. \
|
||||||
Working configuration, is tun enabled in Xray config with specific name (e.g. xray0), and OS level configuration to manage "xray0" interface, applying routing and rules on interface up.
|
For more advanced routing policies or rules, OS level configuration can still manage the named interface (e.g. xray0) when it appears.
|
||||||
This way consistency of system level routing and rules is ensured from single place of responsibility - the OS itself. \
|
This keeps complex system level routing and rules in a single place of responsibility - the OS itself. \
|
||||||
Examples of how to achieve this on a simple Linux system (Ubuntu with systemd-networkd) can be found at the end of this README.
|
Examples of how to achieve this on a simple Linux system (Ubuntu with systemd-networkd) can be found at the end of this README.
|
||||||
|
|
||||||
Due to this inbound not actually being a proxy, the configuration ignore required listen and port options, and never listen on any port. \
|
Due to this inbound not actually being a proxy, the configuration ignore required listen and port options, and never listen on any port. \
|
||||||
|
|||||||
+43
-3
@@ -26,9 +26,10 @@ type LinuxTun struct {
|
|||||||
options *Config
|
options *Config
|
||||||
ownsTun bool
|
ownsTun bool
|
||||||
|
|
||||||
systemRoutes []netlink.Route
|
interfaceAddresses []netlink.Addr
|
||||||
routeMonitorStop chan struct{}
|
systemRoutes []netlink.Route
|
||||||
routeMonitorOnce sync.Once
|
routeMonitorStop chan struct{}
|
||||||
|
routeMonitorOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxTun implements Tun
|
// LinuxTun implements Tun
|
||||||
@@ -172,7 +173,14 @@ func (t *LinuxTun) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := t.setInterfaceAddresses(); err != nil {
|
||||||
|
_ = netlink.LinkSetDown(t.tunLink)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := t.setSystemRoutes(); err != nil {
|
if err := t.setSystemRoutes(); err != nil {
|
||||||
|
_ = t.unsetInterfaceAddresses()
|
||||||
|
_ = netlink.LinkSetDown(t.tunLink)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +201,7 @@ func (t *LinuxTun) Close() error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
_ = t.unsetSystemRoutes()
|
_ = t.unsetSystemRoutes()
|
||||||
|
_ = t.unsetInterfaceAddresses()
|
||||||
|
|
||||||
if t.ownsTun {
|
if t.ownsTun {
|
||||||
_ = netlink.LinkSetDown(t.tunLink)
|
_ = netlink.LinkSetDown(t.tunLink)
|
||||||
@@ -223,6 +232,37 @@ func setinterface(network, address string, fd uintptr, iface *net.Interface) err
|
|||||||
return unix.BindToDevice(int(fd), iface.Name)
|
return unix.BindToDevice(int(fd), iface.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *LinuxTun) setInterfaceAddresses() error {
|
||||||
|
if len(t.options.Gateway) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, address := range t.options.Gateway {
|
||||||
|
addr, err := netlink.ParseAddr(address)
|
||||||
|
if err != nil {
|
||||||
|
_ = t.unsetInterfaceAddresses()
|
||||||
|
return errors.New("invalid interface address ", address).Base(err)
|
||||||
|
}
|
||||||
|
if err := netlink.AddrAdd(t.tunLink, addr); err != nil {
|
||||||
|
_ = t.unsetInterfaceAddresses()
|
||||||
|
return errors.New("failed to add interface address ", address).Base(err)
|
||||||
|
}
|
||||||
|
t.interfaceAddresses = append(t.interfaceAddresses, *addr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *LinuxTun) unsetInterfaceAddresses() error {
|
||||||
|
var errs []error
|
||||||
|
for i := len(t.interfaceAddresses) - 1; i >= 0; i-- {
|
||||||
|
address := t.interfaceAddresses[i]
|
||||||
|
if err := netlink.AddrDel(t.tunLink, &address); err != nil {
|
||||||
|
errs = append(errs, errors.New("failed to delete interface address ", address.String()).Base(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.interfaceAddresses = nil
|
||||||
|
return errors.Combine(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
func (t *LinuxTun) setSystemRoutes() error {
|
func (t *LinuxTun) setSystemRoutes() error {
|
||||||
if len(t.options.AutoSystemRoutingTable) == 0 {
|
if len(t.options.AutoSystemRoutingTable) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user