feat: support to dial domain for udp and support udp for ssr (#17)

This commit is contained in:
mzz 2023-02-18 00:49:35 +08:00 committed by GitHub
parent 663fbb2a59
commit e495ee1b7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 182 additions and 195 deletions

View File

@ -7,12 +7,11 @@ package netutils
import (
"context"
"golang.org/x/net/proxy"
"net"
)
type ContextDialer struct {
Dialer proxy.Dialer
Dialer net.Dialer
}
func (d *ContextDialer) DialContext(ctx context.Context, network, addr string) (c net.Conn, err error) {

View File

@ -9,10 +9,10 @@ import (
"context"
"encoding/binary"
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/pkg/fastrand"
"github.com/mzz2017/softwind/pool"
"golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/proxy"
"io"
"math"
"net/netip"
@ -70,7 +70,7 @@ func SystemDns() (dns netip.AddrPort, err error) {
return systemDns, nil
}
func ResolveNetip(ctx context.Context, d proxy.Dialer, dns netip.AddrPort, host string, typ dnsmessage.Type, tcp bool) (addrs []netip.Addr, err error) {
func ResolveNetip(ctx context.Context, d netproxy.Dialer, dns netip.AddrPort, host string, typ dnsmessage.Type, tcp bool) (addrs []netip.Addr, err error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
if addr, err := netip.ParseAddr(host); err == nil {
@ -122,14 +122,13 @@ func ResolveNetip(ctx context.Context, d proxy.Dialer, dns netip.AddrPort, host
}
// Dial and write.
var network string
cd := &netproxy.ContextDialer{Dialer: d}
var c netproxy.Conn
if tcp {
network = "tcp"
c, err = cd.DialTcpContext(ctx, dns.String())
} else {
network = "udp"
c, err = cd.DialUdpContext(ctx, dns.String())
}
cd := ContextDialer{d}
c, err := cd.DialContext(ctx, network, dns.String())
if err != nil {
return nil, err
}

View File

@ -7,8 +7,8 @@ package netutils
import (
"context"
"github.com/mzz2017/softwind/netproxy"
"golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/proxy"
"net/netip"
)
@ -17,7 +17,7 @@ type Ip46 struct {
Ip6 netip.Addr
}
func ParseIp46(ctx context.Context, dialer proxy.Dialer, dns netip.AddrPort, host string, tcp bool) (ipv46 *Ip46, err error) {
func ParseIp46(ctx context.Context, dialer netproxy.Dialer, dns netip.AddrPort, host string, tcp bool) (ipv46 *Ip46, err error) {
addrs4, err := ResolveNetip(ctx, dialer, dns, host, dnsmessage.TypeA, tcp)
if err != nil {
return nil, err

View File

@ -127,6 +127,10 @@ func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
// This dialer is already alive.
} else {
// Dialer: not alive -> alive.
a.log.WithFields(logrus.Fields{
"dialer": dialer.Name(),
"network": a.CheckTyp.StringWithoutDns(),
}).Infoln("NOT ALIVE -> ALIVE:")
a.dialerToIndex[dialer] = len(a.inorderedAliveDialerSet)
a.inorderedAliveDialerSet = append(a.inorderedAliveDialerSet, dialer)
}
@ -134,6 +138,10 @@ func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
index := a.dialerToIndex[dialer]
if index >= 0 {
// Dialer: alive -> not alive.
a.log.WithFields(logrus.Fields{
"dialer": dialer.Name(),
"network": a.CheckTyp.StringWithoutDns(),
}).Infoln("ALIVE -> NOT ALIVE:")
// Remove the dialer from inorderedAliveDialerSet.
if index >= len(a.inorderedAliveDialerSet) {
a.log.Panicf("index:%v >= len(a.inorderedAliveDialerSet):%v", index, len(a.inorderedAliveDialerSet))

View File

@ -6,6 +6,7 @@
package dialer
import (
"github.com/mzz2017/softwind/netproxy"
"net"
)
@ -13,7 +14,11 @@ type blockDialer struct {
DialCallback func()
}
func (d *blockDialer) Dial(network string, addr string) (c net.Conn, err error) {
func (d *blockDialer) DialTcp(addr string) (c netproxy.Conn, err error) {
d.DialCallback()
return nil, net.ErrClosed
}
func (d *blockDialer) DialUdp(addr string) (c netproxy.PacketConn, err error) {
d.DialCallback()
return nil, net.ErrClosed
}

View File

@ -9,7 +9,9 @@ import (
"context"
"errors"
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/pkg/fastrand"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/sirupsen/logrus"
"github.com/v2rayA/dae/common/consts"
"github.com/v2rayA/dae/common/netutils"
@ -119,7 +121,7 @@ func ParseTcpCheckOption(ctx context.Context, rawURL string) (opt *TcpCheckOptio
if err != nil {
return nil, err
}
ip46, err := netutils.ParseIp46(ctx, SymmetricDirect, systemDns, u.Hostname(), false)
ip46, err := netutils.ParseIp46(ctx, direct.SymmetricDirect, systemDns, u.Hostname(), false)
if err != nil {
return nil, err
}
@ -154,7 +156,7 @@ func ParseCheckDnsOption(ctx context.Context, dnsHostPort string) (opt *CheckDns
if err != nil {
return nil, fmt.Errorf("bad port: %v", err)
}
ip46, err := netutils.ParseIp46(ctx, SymmetricDirect, systemDns, host, false)
ip46, err := netutils.ParseIp46(ctx, direct.SymmetricDirect, systemDns, host, false)
if err != nil {
return nil, err
}
@ -491,12 +493,20 @@ func (d *Dialer) Check(timeout time.Duration,
func (d *Dialer) HttpCheck(ctx context.Context, u *netutils.URL, ip netip.Addr) (ok bool, err error) {
// HTTP(S) check.
cd := netutils.ContextDialer{d.Dialer}
cd := &netproxy.ContextDialer{Dialer: d.Dialer}
cli := http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (c net.Conn, err error) {
// Force to dial "ip".
return cd.DialContext(ctx, "tcp", net.JoinHostPort(ip.String(), u.Port()))
conn, err := cd.DialTcpContext(ctx, net.JoinHostPort(ip.String(), u.Port()))
if err != nil {
return nil, err
}
return &netproxy.FakeNetConn{
Conn: conn,
LAddr: nil,
RAddr: nil,
}, nil
},
},
}

View File

@ -3,8 +3,8 @@ package dialer
import (
"context"
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/sirupsen/logrus"
"golang.org/x/net/proxy"
"sync"
"time"
)
@ -17,7 +17,7 @@ var (
type Dialer struct {
*GlobalOption
instanceOption InstanceOption
proxy.Dialer
netproxy.Dialer
name string
protocol string
link string
@ -43,13 +43,13 @@ type GlobalOption struct {
}
type InstanceOption struct {
CheckEnabled bool
CheckEnabled bool
}
type AliveDialerSetSet map[*AliveDialerSet]int
// NewDialer is for register in general.
func NewDialer(dialer proxy.Dialer, option *GlobalOption, iOption InstanceOption, name string, protocol string, link string) *Dialer {
func NewDialer(dialer netproxy.Dialer, option *GlobalOption, iOption InstanceOption, name string, protocol string, link string) *Dialer {
var collections [6]*collection
for i := range collections {
collections[i] = newCollection()

View File

@ -1,82 +1,13 @@
package dialer
import (
"golang.org/x/net/proxy"
"net"
softwindDirect "github.com/mzz2017/softwind/protocol/direct"
)
var SymmetricDirect = newDirect(false)
var FullconeDirect = newDirect(true)
func NewDirectDialer(option *GlobalOption, fullcone bool) *Dialer {
if fullcone {
return NewDialer(FullconeDirect, option, InstanceOption{CheckEnabled: false}, "direct", "direct", "")
return NewDialer(softwindDirect.FullconeDirect, option, InstanceOption{CheckEnabled: false}, "direct", "direct", "")
} else {
return NewDialer(SymmetricDirect, option, InstanceOption{CheckEnabled: false}, "direct", "direct", "")
return NewDialer(softwindDirect.SymmetricDirect, option, InstanceOption{CheckEnabled: false}, "direct", "direct", "")
}
}
type direct struct {
proxy.Dialer
netDialer *net.Dialer
fullCone bool
}
func newDirect(fullCone bool) proxy.Dialer {
return &direct{
netDialer: &net.Dialer{},
fullCone: fullCone,
}
}
func (d *direct) Dial(network, addr string) (c net.Conn, err error) {
switch network {
case "tcp":
conn, err := d.netDialer.Dial(network, addr)
return conn, err
case "udp":
if d.fullCone {
conn, err := net.ListenUDP(network, nil)
if err != nil {
return nil, err
}
return &directUDPConn{UDPConn: conn, FullCone: true}, nil
} else {
conn, err := d.netDialer.Dial(network, addr)
if err != nil {
return nil, err
}
return &directUDPConn{UDPConn: conn.(*net.UDPConn), FullCone: false}, nil
}
default:
return nil, net.UnknownNetworkError(network)
}
}
type directUDPConn struct {
*net.UDPConn
FullCone bool
}
func (c *directUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
if !c.FullCone {
// FIXME: check the addr
return c.Write(b)
}
return c.UDPConn.WriteTo(b, addr)
}
func (c *directUDPConn) WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error) {
if !c.FullCone {
n, err = c.Write(b)
return n, 0, err
}
return c.UDPConn.WriteMsgUDP(b, oob, addr)
}
func (c *directUDPConn) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) {
if !c.FullCone {
return c.Write(b)
}
return c.UDPConn.WriteToUDP(b, addr)
}

View File

@ -2,6 +2,7 @@ package http
import (
"fmt"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/mzz2017/softwind/protocol/http"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/component/outbound/dialer"
@ -66,7 +67,7 @@ func ParseHTTPURL(link string, option *dialer.GlobalOption) (data *HTTP, err err
func (s *HTTP) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
u := s.URL()
d, err := http.NewHTTPProxy(&u, dialer.SymmetricDirect) // HTTP Proxy does not support full-cone.
d, err := http.NewHTTPProxy(&u, direct.SymmetricDirect) // HTTP Proxy does not support full-cone.
if err != nil {
return nil, err
}

View File

@ -3,12 +3,13 @@ package shadowsocks
import (
"encoding/base64"
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/protocol"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/mzz2017/softwind/protocol/shadowsocks"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/component/outbound/dialer"
"github.com/v2rayA/dae/component/outbound/transport/simpleobfs"
"golang.org/x/net/proxy"
"net"
"net/url"
"strconv"
@ -50,10 +51,10 @@ func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.Instanc
return nil, fmt.Errorf("unsupported shadowsocks encryption method: %v", s.Cipher)
}
var err error
var d proxy.Dialer
var d netproxy.Dialer
switch s.Plugin.Name {
case "simple-obfs":
d = dialer.SymmetricDirect // Simple-obfs does not supports UDP.
d = direct.SymmetricDirect // Simple-obfs does not supports UDP.
switch s.Plugin.Opts.Obfs {
case "http", "tls":
default:
@ -78,7 +79,7 @@ func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.Instanc
return nil, err
}
default:
d = dialer.FullconeDirect // Shadowsocks Proxy supports full-cone.
d = direct.FullconeDirect // Shadowsocks Proxy supports full-cone.
}
d, err = protocol.NewDialer("shadowsocks", d, protocol.Header{
ProxyAddress: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),

View File

@ -3,9 +3,13 @@ package shadowsocksr
import (
"encoding/base64"
"fmt"
"github.com/mzz2017/softwind/protocol"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/mzz2017/softwind/protocol/shadowsocks_stream"
"github.com/mzz2017/softwind/transport/shadowsocksr/obfs"
"github.com/mzz2017/softwind/transport/shadowsocksr/proto"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/component/outbound/dialer"
ssr "github.com/v2rayA/shadowsocksR/client"
"net"
"net/url"
"strconv"
@ -39,21 +43,34 @@ func NewShadowsocksR(option *dialer.GlobalOption, iOption dialer.InstanceOption,
}
func (s *ShadowsocksR) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
u := url.URL{
Scheme: "ssr",
User: url.UserPassword(s.Cipher, s.Password),
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
RawQuery: url.Values{
"protocol": []string{s.Proto},
"protocol_param": []string{s.ProtoParam},
"obfs": []string{s.Obfs},
"obfs_param": []string{s.ObfsParam},
}.Encode(),
}
d, err := ssr.NewSSR(u.String(), dialer.SymmetricDirect, nil) // SSR Proxy does not support full-cone.
d := direct.SymmetricDirect
obfsDialer, err := obfs.NewDialer(d, &obfs.ObfsParam{
ObfsHost: s.Server,
ObfsPort: uint16(s.Port),
Obfs: s.Obfs,
ObfsParam: s.ObfsParam,
})
if err != nil {
return nil, err
}
d = obfsDialer
d, err = shadowsocks_stream.NewDialer(d, protocol.Header{
ProxyAddress: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
Cipher: s.Cipher,
Password: s.Password,
IsClient: true,
ShouldFullCone: false,
})
if err != nil {
return nil, err
}
d = &proto.Dialer{
NextDialer: d,
Protocol: s.Proto,
ProtocolParam: s.ProtoParam,
ObfsOverhead: obfsDialer.ObfsOverhead(),
}
return dialer.NewDialer(d, option, iOption, s.Name, s.Protocol, s.ExportToURL()), nil
}

View File

@ -2,6 +2,7 @@ package socks
import (
"fmt"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/v2rayA/dae/component/outbound/dialer"
//"github.com/mzz2017/softwind/protocol/socks4"
"github.com/mzz2017/softwind/protocol/socks5"
@ -38,7 +39,7 @@ func (s *Socks) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
link := s.ExportToURL()
switch s.Protocol {
case "", "socks", "socks5":
d, err := socks5.NewSocks5Dialer(link, dialer.FullconeDirect) // Socks5 Proxy supports full-cone.
d, err := socks5.NewSocks5Dialer(link, direct.FullconeDirect) // Socks5 Proxy supports full-cone.
if err != nil {
return nil, err
}

View File

@ -2,7 +2,9 @@ package trojan
import (
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/protocol"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/mzz2017/softwind/transport/grpc"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/component/outbound/dialer"
@ -43,7 +45,7 @@ func NewTrojan(option *dialer.GlobalOption, iOption dialer.InstanceOption, link
}
func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (*dialer.Dialer, error) {
d := dialer.FullconeDirect // Trojan Proxy supports full-cone.
d := direct.FullconeDirect // Trojan Proxy supports full-cone.
u := url.URL{
Scheme: "tls",
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
@ -66,8 +68,8 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
Scheme: "ws",
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
RawQuery: url.Values{
"host": []string{s.Host},
"path": []string{s.Path},
"host": []string{s.Host},
"path": []string{s.Path},
}.Encode(),
}
if d, err = ws.NewWs(u.String(), d); err != nil {
@ -79,7 +81,7 @@ func (s *Trojan) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOpti
serviceName = "GunService"
}
d = &grpc.Dialer{
NextDialer: &protocol.DialerConverter{Dialer: d},
NextDialer: &netproxy.ContextDialer{Dialer: d},
ServiceName: serviceName,
ServerName: s.Sni,
AllowInsecure: s.AllowInsecure,

View File

@ -4,13 +4,14 @@ import (
"encoding/base64"
"fmt"
jsoniter "github.com/json-iterator/go"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/protocol"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/mzz2017/softwind/transport/grpc"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/component/outbound/dialer"
"github.com/v2rayA/dae/component/outbound/transport/tls"
"github.com/v2rayA/dae/component/outbound/transport/ws"
"golang.org/x/net/proxy"
"net"
"net/url"
"regexp"
@ -67,12 +68,12 @@ func NewV2Ray(option *dialer.GlobalOption, iOption dialer.InstanceOption, link s
}
func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOption) (data *dialer.Dialer, err error) {
var d proxy.Dialer
var d netproxy.Dialer
switch s.Protocol {
case "vmess":
d = dialer.FullconeDirect // VMess Proxy supports full-cone.
d = direct.FullconeDirect // VMess Proxy supports full-cone.
case "vless":
d = dialer.SymmetricDirect // VLESS Proxy does not yet support full-cone by softwind.
d = direct.SymmetricDirect // VLESS Proxy does not yet support full-cone by softwind.
default:
return nil, fmt.Errorf("V2Ray.Dialer: unexpected protocol: %v", s.Protocol)
}
@ -133,7 +134,7 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
serviceName = "GunService"
}
d = &grpc.Dialer{
NextDialer: &protocol.DialerConverter{Dialer: d},
NextDialer: &netproxy.ContextDialer{Dialer: d},
ServiceName: serviceName,
ServerName: sni,
AllowInsecure: s.AllowInsecure,
@ -147,6 +148,7 @@ func (s *V2Ray) Dialer(option *dialer.GlobalOption, iOption dialer.InstanceOptio
Cipher: "aes-128-gcm",
Password: s.ID,
IsClient: true,
//ShouldFullCone: true,
}); err != nil {
return nil, err
}

View File

@ -7,17 +7,17 @@ package outbound
import (
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/sirupsen/logrus"
"github.com/v2rayA/dae/common/consts"
"github.com/v2rayA/dae/component/outbound/dialer"
"golang.org/x/net/proxy"
"time"
)
var NoAliveDialerError = fmt.Errorf("no alive dialer")
type DialerGroup struct {
proxy.Dialer
netproxy.Dialer
log *logrus.Logger
Name string

View File

@ -6,10 +6,10 @@ import (
"bytes"
"encoding/base64"
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/pkg/fastrand"
"github.com/mzz2017/softwind/pool"
"io"
"net"
"net/http"
"strings"
"sync"
@ -17,7 +17,7 @@ import (
// HTTPObfs is shadowsocks http simple-obfs implementation
type HTTPObfs struct {
net.Conn
netproxy.Conn
host string
port string
path string
@ -92,7 +92,7 @@ func (ho *HTTPObfs) Write(b []byte) (int, error) {
}
// NewHTTPObfs return a HTTPObfs
func NewHTTPObfs(conn net.Conn, host string, port string, path string) net.Conn {
func NewHTTPObfs(conn netproxy.Conn, host string, port string, path string) netproxy.Conn {
if !strings.HasPrefix(path, "/") {
path = "/" + path
}

View File

@ -2,7 +2,7 @@ package simpleobfs
import (
"fmt"
"golang.org/x/net/proxy"
"github.com/mzz2017/softwind/netproxy"
"net"
"net/url"
"strings"
@ -17,7 +17,7 @@ const (
// SimpleObfs is a base http-obfs struct
type SimpleObfs struct {
dialer proxy.Dialer
dialer netproxy.Dialer
obfstype ObfsType
addr string
path string
@ -25,7 +25,7 @@ type SimpleObfs struct {
}
// NewSimpleobfs returns a simpleobfs proxy.
func NewSimpleObfs(s string, d proxy.Dialer) (*SimpleObfs, error) {
func NewSimpleObfs(s string, d netproxy.Dialer) (*SimpleObfs, error) {
u, err := url.Parse(s)
if err != nil {
return nil, fmt.Errorf("simpleobfs: %w", err)
@ -56,13 +56,13 @@ func NewSimpleObfs(s string, d proxy.Dialer) (*SimpleObfs, error) {
return t, nil
}
// Dial connects to the address addr on the network net via the proxy.
func (s *SimpleObfs) Dial(network, addr string) (c net.Conn, err error) {
if network == "udp" {
return nil, fmt.Errorf("simple-obfs does not support UDP")
}
func (s *SimpleObfs) DialUdp(addr string) (conn netproxy.PacketConn, err error) {
return nil, fmt.Errorf("%w: simpleobfs+udp", netproxy.UnsupportedTunnelTypeError)
}
// DialTcp connects to the address addr on the network net via the proxy.
func (s *SimpleObfs) DialTcp(addr string) (c netproxy.Conn, err error) {
rc, err := s.dialer.Dial("tcp", s.addr)
rc, err := s.dialer.DialTcp(s.addr)
if err != nil {
return nil, fmt.Errorf("[simpleobfs]: dial to %s: %w", s.addr, err)
}

View File

@ -5,9 +5,9 @@ package simpleobfs
import (
"bytes"
"encoding/binary"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/pkg/fastrand"
"io"
"net"
"sync"
"time"
)
@ -18,7 +18,7 @@ const (
// TLSObfs is shadowsocks tls simple-obfs implementation
type TLSObfs struct {
net.Conn
netproxy.Conn
server string
remain int
firstRequest bool
@ -112,7 +112,7 @@ func (to *TLSObfs) write(b []byte) (int, error) {
}
// NewTLSObfs return a SimpleObfs
func NewTLSObfs(conn net.Conn, server string) net.Conn {
func NewTLSObfs(conn netproxy.Conn, server string) netproxy.Conn {
return &TLSObfs{
Conn: conn,
server: server,

View File

@ -3,14 +3,13 @@ package tls
import (
"crypto/tls"
"fmt"
"golang.org/x/net/proxy"
"net"
"github.com/mzz2017/softwind/netproxy"
"net/url"
)
// Tls is a base Tls struct
type Tls struct {
dialer proxy.Dialer
dialer netproxy.Dialer
addr string
serverName string
skipVerify bool
@ -18,7 +17,7 @@ type Tls struct {
}
// NewTls returns a Tls infra.
func NewTls(s string, d proxy.Dialer) (*Tls, error) {
func NewTls(s string, d netproxy.Dialer) (*Tls, error) {
u, err := url.Parse(s)
if err != nil {
return nil, fmt.Errorf("NewTls: %w", err)
@ -48,13 +47,20 @@ func NewTls(s string, d proxy.Dialer) (*Tls, error) {
return t, nil
}
func (s *Tls) Dial(network, addr string) (conn net.Conn, err error) {
rc, err := s.dialer.Dial("tcp", addr)
func (s *Tls) DialUdp(addr string) (conn netproxy.PacketConn, err error) {
return nil, fmt.Errorf("%w: tls+udp", netproxy.UnsupportedTunnelTypeError)
}
func (s *Tls) DialTcp(addr string) (conn netproxy.Conn, err error) {
rc, err := s.dialer.DialTcp(addr)
if err != nil {
return nil, fmt.Errorf("[Tls]: dial to %s: %w", s.addr, err)
}
tlsConn := tls.Client(rc, s.tlsConfig)
tlsConn := tls.Client(&netproxy.FakeNetConn{
Conn: rc,
LAddr: nil,
RAddr: nil,
}, s.tlsConfig)
if err := tlsConn.Handshake(); err != nil {
return nil, err
}

View File

@ -4,7 +4,7 @@ import (
"crypto/tls"
"fmt"
"github.com/gorilla/websocket"
"golang.org/x/net/proxy"
"github.com/mzz2017/softwind/netproxy"
"net"
"net/http"
"net/url"
@ -13,14 +13,14 @@ import (
// Ws is a base Ws struct
type Ws struct {
dialer proxy.Dialer
dialer netproxy.Dialer
wsAddr string
header http.Header
wsDialer *websocket.Dialer
}
// NewWs returns a Ws infra.
func NewWs(s string, d proxy.Dialer) (*Ws, error) {
func NewWs(s string, d netproxy.Dialer) (*Ws, error) {
u, err := url.Parse(s)
if err != nil {
return nil, fmt.Errorf("NewWs: %w", err)
@ -44,7 +44,17 @@ func NewWs(s string, d proxy.Dialer) (*Ws, error) {
}
t.wsAddr = wsUrl.String() + u.Path
t.wsDialer = &websocket.Dialer{
NetDial: d.Dial,
NetDial: func(network, addr string) (net.Conn, error) {
c, err := d.DialTcp(addr)
if err != nil {
return nil, err
}
return &netproxy.FakeNetConn{
Conn: c,
LAddr: nil,
RAddr: nil,
}, nil
},
//Subprotocols: []string{"binary"},
}
if u.Scheme == "wss" {
@ -57,8 +67,12 @@ func NewWs(s string, d proxy.Dialer) (*Ws, error) {
return t, nil
}
// Dial connects to the address addr on the network net via the infra.
func (s *Ws) Dial(network, addr string) (net.Conn, error) {
func (s *Ws) DialUdp(addr string) (netproxy.PacketConn, error) {
return nil, fmt.Errorf("%w: ws+udp", netproxy.UnsupportedTunnelTypeError)
}
// DialTcp connects to the address addr on the network net via the infra.
func (s *Ws) DialTcp(addr string) (netproxy.Conn, error) {
rc, _, err := s.wsDialer.Dial(s.wsAddr, s.header)
if err != nil {
return nil, fmt.Errorf("[Ws]: dial to %s: %w", s.wsAddr, err)

View File

@ -431,7 +431,7 @@ func (c *ControlPlane) ChooseDialTarget(outbound consts.OutboundIndex, dst netip
c.log.WithFields(logrus.Fields{
"from": dst.String(),
"to": dialTarget,
}).Debugln("Reset dial target to domain")
}).Debugln("Rewrite dial target to domain")
}
return dialTarget
}

View File

@ -122,7 +122,7 @@ func (c *ControlPlane) lookupDnsRespCache(domain string, t dnsmessage.Type) (cac
return nil
}
func (c *ControlPlane) LookupDnsRespCache(msg *dnsmessage.Message) (resp []byte) {
func (c *ControlPlane) LookupDnsRespCache_(msg *dnsmessage.Message) (resp []byte) {
if len(msg.Questions) == 0 {
return nil
}
@ -140,6 +140,7 @@ func (c *ControlPlane) LookupDnsRespCache(msg *dnsmessage.Message) (resp []byte)
cache.FillInto(msg)
b, err := msg.Pack()
if err != nil {
c.log.Warnf("failed to pack: %v", err)
return nil
}
if err = c.BatchUpdateDomainRouting(cache); err != nil {

View File

@ -8,10 +8,10 @@ package control
import (
"context"
"fmt"
"github.com/mzz2017/softwind/protocol/direct"
"github.com/v2rayA/dae/common"
"github.com/v2rayA/dae/common/consts"
"github.com/v2rayA/dae/common/netutils"
"github.com/v2rayA/dae/component/outbound/dialer"
"net/url"
"strconv"
"sync"
@ -79,7 +79,7 @@ func ResolveDnsUpstream(ctx context.Context, dnsUpstream *url.URL) (up *DnsUpstr
}
}()
ip46, err := netutils.ParseIp46(ctx, dialer.SymmetricDirect, systemDns, hostname, false)
ip46, err := netutils.ParseIp46(ctx, direct.SymmetricDirect, systemDns, hostname, false)
if err != nil {
return nil, fmt.Errorf("failed to resolve dns_upstream: %w", err)
}

View File

@ -7,6 +7,7 @@ package control
import (
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/pkg/zeroalloc/io"
"github.com/sirupsen/logrus"
"github.com/v2rayA/dae/common"
@ -95,7 +96,7 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
}).Infof("%v <-> %v", RefineSourceToShow(src, dst.Addr(), consts.LanWanFlag_NotApplicable), RefineAddrPortToShow(dst))
// Dial and relay.
rConn, err := d.Dial("tcp", c.ChooseDialTarget(outboundIndex, dst, domain))
rConn, err := d.DialTcp(c.ChooseDialTarget(outboundIndex, dst, domain))
if err != nil {
return fmt.Errorf("failed to dial %v: %w", dst, err)
}
@ -117,7 +118,7 @@ type WriteCloser interface {
CloseWrite() error
}
func RelayTCP(lConn, rConn net.Conn) (err error) {
func RelayTCP(lConn, rConn netproxy.Conn) (err error) {
eCh := make(chan error, 1)
go func() {
_, e := io.Copy(rConn, lConn)

View File

@ -176,7 +176,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
var dummyFrom *netip.AddrPort
destToSend := realDst
if isDns {
if resp := c.LookupDnsRespCache(dnsMessage); resp != nil {
if resp := c.LookupDnsRespCache_(dnsMessage); resp != nil {
// Send cache to client directly.
if err = sendPkt(resp, destToSend, realSrc, src, lConn, lanWanFlag); err != nil {
return fmt.Errorf("failed to write cached DNS resp: %w", err)
@ -301,8 +301,11 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
// So se should trust home devices even if they make rush-answer (or looks like).
return outboundIndex == consts.OutboundDirect && !common.ConvergeIp(from.Addr()).IsPrivate()
})
// Dial and send.
// TODO: Rewritten domain should not use full-cone (such as VMess Packet Addr).
// Maybe we should set up a mapping for UDP: Dialer + Target Domain => Remote Resolved IP.
destToSend = netip.AddrPortFrom(common.ConvergeIp(destToSend.Addr()), destToSend.Port())
tgtToSend := c.ChooseDialTarget(outboundIndex, destToSend, domain)
switch l4proto {
case consts.L4ProtoStr_UDP:
// Get udp endpoint.
@ -318,14 +321,14 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
DialerFunc: func() (*dialer.Dialer, error) {
return dialerForNew, nil
},
// FIXME: how to write domain into UDP tunnel?
Target: destToSend,
Target: tgtToSend,
})
if err != nil {
return fmt.Errorf("failed to GetOrCreate (policy: %v): %w", outbound.GetSelectionPolicy(), err)
}
// If the udp endpoint has been not alive, remove it from pool and get a new one.
if !isNew && !ue.Dialer.MustGetAlive(networkType) {
if !isNew && outbound.GetSelectionPolicy() != consts.DialerSelectionPolicy_Fixed && !ue.Dialer.MustGetAlive(networkType) {
c.log.WithFields(logrus.Fields{
"src": RefineSourceToShow(realSrc, realDst.Addr(), lanWanFlag),
"network": networkType.String(),
@ -339,8 +342,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
// This is real dialer.
realDialer = ue.Dialer
//log.Printf("WriteToUDPAddrPort->%v", destToSend)
_, err = ue.WriteToUDPAddrPort(data, destToSend)
_, err = ue.WriteTo(data, tgtToSend)
if err != nil {
c.log.WithFields(logrus.Fields{
"to": destToSend.String(),
@ -364,7 +366,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
// We can block because we are in a coroutine.
conn, err := dialerForNew.Dial("tcp", c.ChooseDialTarget(outboundIndex, destToSend, domain))
conn, err := dialerForNew.DialTcp(tgtToSend)
if err != nil {
return fmt.Errorf("failed to dial proxy to tcp: %w", err)
}
@ -395,7 +397,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
buf = bReq
}
var n int
if n, err = conn.Read(buf[:respLen]); err != nil {
if n, err = io.ReadFull(conn, buf[:respLen]); err != nil {
return fmt.Errorf("failed to read DNS resp payload: %w", err)
}
if err = udpHandler(buf[:n], destToSend); err != nil {

View File

@ -8,9 +8,9 @@ package control
import (
"errors"
"fmt"
"github.com/mzz2017/softwind/netproxy"
"github.com/mzz2017/softwind/pool"
"github.com/v2rayA/dae/component/outbound/dialer"
"net"
"net/netip"
"sync"
"time"
@ -19,7 +19,7 @@ import (
type UdpHandler func(data []byte, from netip.AddrPort) error
type UdpEndpoint struct {
conn net.PacketConn
conn netproxy.PacketConn
// mu protects deadlineTimer
mu sync.Mutex
deadlineTimer *time.Timer
@ -40,7 +40,7 @@ func (ue *UdpEndpoint) start() {
ue.mu.Lock()
ue.deadlineTimer.Reset(ue.NatTimeout)
ue.mu.Unlock()
if err = ue.handler(buf[:n], from.(*net.UDPAddr).AddrPort()); err != nil {
if err = ue.handler(buf[:n], from); err != nil {
if errors.Is(err, SuspectedRushAnswerError) {
continue
}
@ -52,8 +52,8 @@ func (ue *UdpEndpoint) start() {
ue.mu.Unlock()
}
func (ue *UdpEndpoint) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) {
return ue.conn.WriteTo(b, net.UDPAddrFromAddrPort(addr))
func (ue *UdpEndpoint) WriteTo(b []byte, addr string) (int, error) {
return ue.conn.WriteTo(b, addr)
}
func (ue *UdpEndpoint) Close() error {
@ -75,7 +75,7 @@ type UdpEndpointOptions struct {
NatTimeout time.Duration
DialerFunc func() (*dialer.Dialer, error)
// Target is useful only if the underlay does not support Full-cone.
Target netip.AddrPort
Target string
}
var DefaultUdpEndpointPool = NewUdpEndpointPool()
@ -100,6 +100,7 @@ func (p *UdpEndpointPool) Remove(lAddr netip.AddrPort, udpEndpoint *UdpEndpoint)
}
func (p *UdpEndpointPool) GetOrCreate(lAddr netip.AddrPort, createOption *UdpEndpointOptions) (udpEndpoint *UdpEndpoint, isNew bool, err error) {
// TODO: fine-grained lock.
p.mu.Lock()
defer p.mu.Unlock()
ue, ok := p.pool[lAddr]
@ -120,15 +121,15 @@ func (p *UdpEndpointPool) GetOrCreate(lAddr netip.AddrPort, createOption *UdpEnd
return nil, true, err
}
udpConn, err := d.Dial("udp", createOption.Target.String())
udpConn, err := d.DialUdp(createOption.Target)
if err != nil {
return nil, true, err
}
if _, ok = udpConn.(net.PacketConn); !ok {
if _, ok = udpConn.(netproxy.PacketConn); !ok {
return nil, true, fmt.Errorf("protocol does not support udp")
}
ue = &UdpEndpoint{
conn: udpConn.(net.PacketConn),
conn: udpConn.(netproxy.PacketConn),
deadlineTimer: time.AfterFunc(createOption.NatTimeout, func() {
p.mu.Lock()
defer p.mu.Unlock()

View File

@ -51,9 +51,10 @@ global {
# 1. "ip". Dial proxy using the IP from DNS directly. This allows your ipv4, ipv6 to choose the optimal path
# respectively, and makes the IP version requested by the application meet expectations. For example, if you
# use curl -4 ip.sb, you will request IPv4 via proxy and get a IPv4 echo. And curl -6 ip.sb will request IPv6.
# This may solve some wierd full-cone problem if your are be your node support that.
# 2. "domain". Dial proxy using the domain from sniffing. This will relieve DNS pollution problem to a great extent
# if have impure DNS environment. This policy does not impact routing. That is to say, domain reset will be
# after traffic split.
# if have impure DNS environment. Generally, this mode brings faster response time. This policy does not impact
# routing. That is to say, domain rewrite will be after traffic split and dae will not resolve IP and re-route.
dial_mode: domain
}

5
go.mod
View File

@ -9,14 +9,14 @@ require (
github.com/gorilla/websocket v1.5.0
github.com/json-iterator/go v1.1.12
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/mzz2017/softwind v0.0.0-20230213075606-e58b03d6ac4b
github.com/mzz2017/softwind v0.0.0-20230217163103-acb4981669fe
github.com/safchain/ethtool v0.0.0-20230116090318-67cc41908669
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.6.1
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230201041341-1758ee5161c1
github.com/v2rayA/shadowsocksR v1.0.4
github.com/vishvananda/netlink v1.1.0
github.com/x-cray/logrus-prefixed-formatter v0.5.2
golang.org/x/crypto v0.5.0
golang.org/x/net v0.5.0
golang.org/x/sys v0.4.0
google.golang.org/protobuf v1.28.1
@ -44,7 +44,6 @@ require (
github.com/stretchr/testify v1.8.1 // indirect
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
gitlab.com/yawning/chacha20.git v0.0.0-20190903091407-6d1cb28dc72c // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/term v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect

18
go.sum
View File

@ -17,7 +17,6 @@ github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fp
github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152 h1:ED31mPIxDJnrLt9W9dH5xgd/6KjzEACKHBVGQ33czc0=
github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152/go.mod h1:I9fhc/EvSg88cDxmfQ47v35Ssz9rlFunL/KY0A1JAYI=
github.com/ebfe/rc2 v0.0.0-20131011165748-24b9757f5521 h1:fBHFH+Y/GPGFGo7LIrErQc3p2MeAhoIQNgaxPWYsSxk=
github.com/ebfe/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:ucvhdsUCE3TH0LoLRb6ShHiJl8e39dGlx6A4g/ujlow=
github.com/eknkc/basex v1.0.1 h1:TcyAkqh4oJXgV3WYyL4KEfCMk9W8oJCpmx1bo+jVgKY=
github.com/eknkc/basex v1.0.1/go.mod h1:k/F/exNEHFdbs3ZHuasoP2E7zeWwZblG84Y7Z59vQRo=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
@ -51,8 +50,6 @@ github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@ -69,9 +66,8 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mzz2017/disk-bloom v1.0.1 h1:rEF9MiXd9qMW3ibRpqcerLXULoTgRlM21yqqJl1B90M=
github.com/mzz2017/disk-bloom v1.0.1/go.mod h1:JLHETtUu44Z6iBmsqzkOtFlRvXSlKnxjwiBRDapizDI=
github.com/mzz2017/softwind v0.0.0-20230213075606-e58b03d6ac4b h1:Hwx9RlLBGWWzr8M3zIoL5bnrhPiT3mHDkawkuCb1E7Q=
github.com/mzz2017/softwind v0.0.0-20230213075606-e58b03d6ac4b/go.mod h1:K1nXwtBokwEsfOfdT/5zV6R8QabGkyhcR0iuTrRZcYY=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/mzz2017/softwind v0.0.0-20230217163103-acb4981669fe h1:i2YtHdgl0oYWKixm/kX5skbrhaAQj1ZHR5RZKyqaySY=
github.com/mzz2017/softwind v0.0.0-20230217163103-acb4981669fe/go.mod h1:V8GFOtdpTgzCJtCVXRqjmdDsY+PIhCCx4JpD0zq8Z7I=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@ -91,7 +87,6 @@ github.com/safchain/ethtool v0.0.0-20230116090318-67cc41908669 h1:2uB3lH1zhL5dQf
github.com/safchain/ethtool v0.0.0-20230116090318-67cc41908669/go.mod h1:Op2Wq4eQEVKmpd+02CtUlkHYjL2vQJ+wyzyc3/KGqFk=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
@ -101,7 +96,6 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@ -113,8 +107,6 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230201041341-1758ee5161c1 h1:Ke91ZtZItOO8/SK8nhZ1tXfXcUxj4Meq5pET/L9bHII=
github.com/v2rayA/dae-config-dist/go/dae_config v0.0.0-20230201041341-1758ee5161c1/go.mod h1:JiTWeZybOkBfCqv/fy5jbFhXTxuLlyrI76gRNazz2sU=
github.com/v2rayA/shadowsocksR v1.0.4 h1:65Ltdy+I/DnlkQTJj+R+X85zhZ63ORE1Roy+agAcF/s=
github.com/v2rayA/shadowsocksR v1.0.4/go.mod h1:CyOhDLy8/AKedsi16xRYAMmkxSCH1ukJPaacaTdRfQg=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
@ -128,7 +120,6 @@ gitlab.com/yawning/chacha20.git v0.0.0-20190903091407-6d1cb28dc72c/go.mod h1:3x6
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
@ -139,7 +130,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -152,19 +142,16 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -193,7 +180,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=