Merge remote-tracking branch 'yaling888/with-tun' into Alpha
# Conflicts: # listener/tun/tun_adapter.go
This commit is contained in:
commit
29b8076c75
7 changed files with 91 additions and 47 deletions
|
@ -147,10 +147,10 @@ type Options struct {
|
||||||
|
|
||||||
// New return Pool instance
|
// New return Pool instance
|
||||||
func New(options Options) (*Pool, error) {
|
func New(options Options) (*Pool, error) {
|
||||||
min := ipToUint(options.IPNet.IP) + 2
|
min := ipToUint(options.IPNet.IP) + 3
|
||||||
|
|
||||||
ones, bits := options.IPNet.Mask.Size()
|
ones, bits := options.IPNet.Mask.Size()
|
||||||
total := 1<<uint(bits-ones) - 3
|
total := 1<<uint(bits-ones) - 4
|
||||||
|
|
||||||
if total <= 0 {
|
if total <= 0 {
|
||||||
return nil, errors.New("ipnet don't have valid ip")
|
return nil, errors.New("ipnet don't have valid ip")
|
||||||
|
@ -160,7 +160,7 @@ func New(options Options) (*Pool, error) {
|
||||||
pool := &Pool{
|
pool := &Pool{
|
||||||
min: min,
|
min: min,
|
||||||
max: max,
|
max: max,
|
||||||
gateway: min - 1,
|
gateway: min - 2,
|
||||||
broadcast: max + 1,
|
broadcast: max + 1,
|
||||||
host: options.Host,
|
host: options.Host,
|
||||||
ipnet: options.IPNet,
|
ipnet: options.IPNet,
|
||||||
|
|
|
@ -49,7 +49,7 @@ func createCachefileStore(options Options) (*Pool, string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPool_Basic(t *testing.T) {
|
func TestPool_Basic(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/29")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.0/28")
|
||||||
pools, tempfile, err := createPools(Options{
|
pools, tempfile, err := createPools(Options{
|
||||||
IPNet: ipnet,
|
IPNet: ipnet,
|
||||||
Size: 10,
|
Size: 10,
|
||||||
|
@ -62,21 +62,22 @@ func TestPool_Basic(t *testing.T) {
|
||||||
last := pool.Lookup("bar.com")
|
last := pool.Lookup("bar.com")
|
||||||
bar, exist := pool.LookBack(last)
|
bar, exist := pool.LookBack(last)
|
||||||
|
|
||||||
assert.True(t, first.Equal(net.IP{192, 168, 0, 2}))
|
assert.True(t, first.Equal(net.IP{192, 168, 0, 3}))
|
||||||
assert.Equal(t, pool.Lookup("foo.com"), net.IP{192, 168, 0, 2})
|
assert.Equal(t, pool.Lookup("foo.com"), net.IP{192, 168, 0, 3})
|
||||||
assert.True(t, last.Equal(net.IP{192, 168, 0, 3}))
|
assert.True(t, last.Equal(net.IP{192, 168, 0, 4}))
|
||||||
assert.True(t, exist)
|
assert.True(t, exist)
|
||||||
assert.Equal(t, bar, "bar.com")
|
assert.Equal(t, bar, "bar.com")
|
||||||
assert.Equal(t, pool.Gateway(), net.IP{192, 168, 0, 1})
|
assert.Equal(t, pool.Gateway(), net.IP{192, 168, 0, 1})
|
||||||
|
assert.Equal(t, pool.Broadcast(), net.IP{192, 168, 0, 15})
|
||||||
assert.Equal(t, pool.IPNet().String(), ipnet.String())
|
assert.Equal(t, pool.IPNet().String(), ipnet.String())
|
||||||
assert.True(t, pool.Exist(net.IP{192, 168, 0, 3}))
|
assert.True(t, pool.Exist(net.IP{192, 168, 0, 4}))
|
||||||
assert.False(t, pool.Exist(net.IP{192, 168, 0, 4}))
|
assert.False(t, pool.Exist(net.IP{192, 168, 0, 5}))
|
||||||
assert.False(t, pool.Exist(net.ParseIP("::1")))
|
assert.False(t, pool.Exist(net.ParseIP("::1")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPool_CycleUsed(t *testing.T) {
|
func TestPool_CycleUsed(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/29")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.16/28")
|
||||||
pools, tempfile, err := createPools(Options{
|
pools, tempfile, err := createPools(Options{
|
||||||
IPNet: ipnet,
|
IPNet: ipnet,
|
||||||
Size: 10,
|
Size: 10,
|
||||||
|
@ -87,7 +88,7 @@ func TestPool_CycleUsed(t *testing.T) {
|
||||||
for _, pool := range pools {
|
for _, pool := range pools {
|
||||||
foo := pool.Lookup("foo.com")
|
foo := pool.Lookup("foo.com")
|
||||||
bar := pool.Lookup("bar.com")
|
bar := pool.Lookup("bar.com")
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 9; i++ {
|
||||||
pool.Lookup(fmt.Sprintf("%d.com", i))
|
pool.Lookup(fmt.Sprintf("%d.com", i))
|
||||||
}
|
}
|
||||||
baz := pool.Lookup("baz.com")
|
baz := pool.Lookup("baz.com")
|
||||||
|
@ -98,7 +99,7 @@ func TestPool_CycleUsed(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPool_Skip(t *testing.T) {
|
func TestPool_Skip(t *testing.T) {
|
||||||
_, ipnet, _ := net.ParseCIDR("192.168.0.1/30")
|
_, ipnet, _ := net.ParseCIDR("192.168.0.1/29")
|
||||||
tree := trie.New()
|
tree := trie.New()
|
||||||
tree.Insert("example.com", tree)
|
tree.Insert("example.com", tree)
|
||||||
pools, tempfile, err := createPools(Options{
|
pools, tempfile, err := createPools(Options{
|
||||||
|
@ -169,8 +170,8 @@ func TestPool_Clone(t *testing.T) {
|
||||||
|
|
||||||
first := pool.Lookup("foo.com")
|
first := pool.Lookup("foo.com")
|
||||||
last := pool.Lookup("bar.com")
|
last := pool.Lookup("bar.com")
|
||||||
assert.True(t, first.Equal(net.IP{192, 168, 0, 2}))
|
assert.True(t, first.Equal(net.IP{192, 168, 0, 3}))
|
||||||
assert.True(t, last.Equal(net.IP{192, 168, 0, 3}))
|
assert.True(t, last.Equal(net.IP{192, 168, 0, 4}))
|
||||||
|
|
||||||
newPool, _ := New(Options{
|
newPool, _ := New(Options{
|
||||||
IPNet: ipnet,
|
IPNet: ipnet,
|
||||||
|
|
|
@ -3,11 +3,19 @@ package commons
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
|
"github.com/Dreamacro/clash/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Routes = []string{"1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/6", "8.0.0.0/5", "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/1"}
|
var (
|
||||||
|
defaultRoutes = []string{"1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/6", "8.0.0.0/5", "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/1"}
|
||||||
|
|
||||||
func IPv4MaskString(bits int) string {
|
defaultInterfaceMonitorDuration = 20 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
func ipv4MaskString(bits int) string {
|
||||||
m := net.CIDRMask(bits, 32)
|
m := net.CIDRMask(bits, 32)
|
||||||
if len(m) != 4 {
|
if len(m) != 4 {
|
||||||
panic("ipv4Mask: len must be 4 bytes")
|
panic("ipv4Mask: len must be 4 bytes")
|
||||||
|
@ -15,3 +23,27 @@ func IPv4MaskString(bits int) string {
|
||||||
|
|
||||||
return fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
|
return fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func defaultInterfaceChangeMonitor() {
|
||||||
|
t := time.NewTicker(defaultInterfaceMonitorDuration)
|
||||||
|
defer t.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
<-t.C
|
||||||
|
|
||||||
|
interfaceName, err := GetAutoDetectInterface()
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("[TUN] default interface monitor exited, cause: %v", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
old := dialer.DefaultInterface.Load()
|
||||||
|
if interfaceName == old {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dialer.DefaultInterface.Store(interfaceName)
|
||||||
|
|
||||||
|
log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, interfaceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetAutoDetectInterface() (string, error) {
|
func GetAutoDetectInterface() (string, error) {
|
||||||
return cmd.ExecCmd("bash -c netstat -rnf inet | grep 'default' | awk -F ' ' 'NR==1{print $6}' | xargs echo -n")
|
return cmd.ExecCmd("bash -c route -n get default | grep 'interface:' | awk -F ' ' 'NR==1{print $2}' | xargs echo -n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute bool) error {
|
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute bool) error {
|
||||||
|
@ -20,8 +20,8 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||||
var (
|
var (
|
||||||
interfaceName = dev.Name()
|
interfaceName = dev.Name()
|
||||||
ip = addr.Masked().Addr().Next()
|
ip = addr.Masked().Addr().Next()
|
||||||
gw = ip
|
gw = ip.Next()
|
||||||
netmask = IPv4MaskString(addr.Bits())
|
netmask = ipv4MaskString(addr.Bits())
|
||||||
)
|
)
|
||||||
|
|
||||||
cmdStr := fmt.Sprintf("ifconfig %s inet %s netmask %s %s", interfaceName, ip, netmask, gw)
|
cmdStr := fmt.Sprintf("ifconfig %s inet %s netmask %s %s", interfaceName, ip, netmask, gw)
|
||||||
|
@ -31,10 +31,10 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// _, err = cmd.ExecCmd(fmt.Sprintf("ipconfig set %s automatic-v6", interfaceName))
|
_, err = cmd.ExecCmd(fmt.Sprintf("ipconfig set %s automatic-v6", interfaceName))
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return err
|
return err
|
||||||
// }
|
}
|
||||||
|
|
||||||
if autoRoute {
|
if autoRoute {
|
||||||
err = configInterfaceRouting(interfaceName, addr)
|
err = configInterfaceRouting(interfaceName, addr)
|
||||||
|
@ -43,16 +43,20 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||||
}
|
}
|
||||||
|
|
||||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
|
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
|
||||||
routes := append(Routes, addr.String())
|
var (
|
||||||
|
routes = append(defaultRoutes, addr.String())
|
||||||
|
gateway = addr.Masked().Addr().Next()
|
||||||
|
)
|
||||||
|
|
||||||
for _, route := range routes {
|
for _, destination := range routes {
|
||||||
if err := execRouterCmd("add", "-inet", route, interfaceName); err != nil {
|
if _, err := cmd.ExecCmd(fmt.Sprintf("route add -net %s %s", destination, gateway)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return execRouterCmd("add", "-inet6", "2000::/3", interfaceName)
|
go defaultInterfaceChangeMonitor()
|
||||||
return nil
|
|
||||||
|
return execRouterCmd("add", "-inet6", "2000::/3", interfaceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func execRouterCmd(action, inet, route string, interfaceName string) error {
|
func execRouterCmd(action, inet, route string, interfaceName string) error {
|
||||||
|
|
|
@ -36,11 +36,14 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||||
|
|
||||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
|
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
|
||||||
linkIP := addr.Masked().Addr().Next()
|
linkIP := addr.Masked().Addr().Next()
|
||||||
for _, route := range Routes {
|
for _, route := range defaultRoutes {
|
||||||
if err := execRouterCmd("add", route, interfaceName, linkIP.String()); err != nil {
|
if err := execRouterCmd("add", route, interfaceName, linkIP.String()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
go defaultInterfaceChangeMonitor()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ import (
|
||||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var wintunInterfaceName string
|
||||||
|
|
||||||
func GetAutoDetectInterface() (string, error) {
|
func GetAutoDetectInterface() (string, error) {
|
||||||
ifname, err := getAutoDetectInterfaceByFamily(winipcfg.AddressFamily(windows.AF_INET))
|
ifname, err := getAutoDetectInterfaceByFamily(winipcfg.AddressFamily(windows.AF_INET))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -30,7 +32,7 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||||
var err error
|
var err error
|
||||||
startOver:
|
startOver:
|
||||||
if tryTimes > 0 {
|
if tryTimes > 0 {
|
||||||
log.Infoln("Retrying interface configuration after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
|
log.Infoln("[TUN] retrying interface configuration after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
retryOnFailure = retryOnFailure && tryTimes < 15
|
retryOnFailure = retryOnFailure && tryTimes < 15
|
||||||
}
|
}
|
||||||
|
@ -199,6 +201,10 @@ startOver:
|
||||||
return fmt.Errorf("unable to set DNS %s %s: %w", "198.18.0.2", "nil", err)
|
return fmt.Errorf("unable to set DNS %s %s: %w", "198.18.0.2", "nil", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wintunInterfaceName = dev.Name()
|
||||||
|
|
||||||
|
go defaultInterfaceChangeMonitor()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +227,7 @@ func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, add
|
||||||
for address := iface.FirstUnicastAddress; address != nil; address = address.Next {
|
for address := iface.FirstUnicastAddress; address != nil; address = address.Next {
|
||||||
if ip, _ := netip.AddrFromSlice(address.Address.IP()); addrHash[ip] {
|
if ip, _ := netip.AddrFromSlice(address.Address.IP()); addrHash[ip] {
|
||||||
prefix := netip.PrefixFrom(ip, int(address.OnLinkPrefixLength))
|
prefix := netip.PrefixFrom(ip, int(address.OnLinkPrefixLength))
|
||||||
log.Infoln("Cleaning up stale address %s from interface ‘%s’", prefix.String(), iface.FriendlyName())
|
log.Infoln("[TUN] cleaning up stale address %s from interface ‘%s’", prefix.String(), iface.FriendlyName())
|
||||||
_ = iface.LUID.DeleteIPAddress(prefix)
|
_ = iface.LUID.DeleteIPAddress(prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,6 +254,10 @@ func getAutoDetectInterfaceByFamily(family winipcfg.AddressFamily) (string, erro
|
||||||
|
|
||||||
ifname := iface.FriendlyName()
|
ifname := iface.FriendlyName()
|
||||||
|
|
||||||
|
if wintunInterfaceName == ifname {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for gatewayAddress := iface.FirstGatewayAddress; gatewayAddress != nil; gatewayAddress = gatewayAddress.Next {
|
for gatewayAddress := iface.FirstGatewayAddress; gatewayAddress != nil; gatewayAddress = gatewayAddress.Next {
|
||||||
nextHop, _ := netip.AddrFromSlice(gatewayAddress.Address.IP())
|
nextHop, _ := netip.AddrFromSlice(gatewayAddress.Address.IP())
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import (
|
||||||
// New TunAdapter
|
// New TunAdapter
|
||||||
func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) {
|
func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) {
|
||||||
var (
|
var (
|
||||||
tunAddress = netip.MustParsePrefix("198.18.0.1/16")
|
tunAddress, _ = netip.ParsePrefix("198.18.0.1/16")
|
||||||
devName = tunConf.Device
|
devName = tunConf.Device
|
||||||
stackType = tunConf.Stack
|
stackType = tunConf.Stack
|
||||||
autoRoute = tunConf.AutoRoute
|
autoRoute = tunConf.AutoRoute
|
||||||
|
@ -49,20 +49,14 @@ func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.
|
||||||
process.AppendLocalIPs(tunAddress.Masked().Addr().Next().AsSlice())
|
process.AppendLocalIPs(tunAddress.Masked().Addr().Next().AsSlice())
|
||||||
|
|
||||||
// open tun device
|
// open tun device
|
||||||
tunDevice, err = parseDevice(devName, uint32(mtu))
|
|
||||||
if err != nil {
|
|
||||||
for i := 1; i < 3; i++ {
|
for i := 1; i < 3; i++ {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
tunDevice, err = parseDevice(devName, uint32(mtu))
|
tunDevice, err = parseDevice(devName, uint32(mtu))
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't open tun: %w", err)
|
return nil, fmt.Errorf("can't open tun: %w", err)
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// new ip stack
|
// new ip stack
|
||||||
switch stackType {
|
switch stackType {
|
||||||
case C.TunGvisor:
|
case C.TunGvisor:
|
||||||
|
@ -116,7 +110,7 @@ func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.
|
||||||
func generateDeviceName() string {
|
func generateDeviceName() string {
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
return tun.Driver + "://utun"
|
return tun.Driver + "://Meta"
|
||||||
case "windows":
|
case "windows":
|
||||||
return tun.Driver + "://Meta"
|
return tun.Driver + "://Meta"
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue