diff --git a/listener/tun/ipstack/lwip/dns.go b/listener/tun/ipstack/lwip/dns.go deleted file mode 100644 index 6a314c08..00000000 --- a/listener/tun/ipstack/lwip/dns.go +++ /dev/null @@ -1,87 +0,0 @@ -package lwip - -import ( - "encoding/binary" - "io" - "net" - "time" - - "github.com/Dreamacro/clash/component/resolver" - D "github.com/Dreamacro/clash/listener/tun/ipstack/commons" - "github.com/Dreamacro/clash/log" - "github.com/yaling888/go-lwip" -) - -const defaultDnsReadTimeout = time.Second * 8 - -func shouldHijackDns(dnsIP net.IP, targetIp net.IP, targetPort int) bool { - if targetPort != 53 { - return false - } - - return dnsIP.Equal(net.IPv4zero) || dnsIP.Equal(targetIp) -} - -func hijackUDPDns(conn golwip.UDPConn, pkt []byte, addr *net.UDPAddr) { - go func() { - defer func(conn golwip.UDPConn) { - _ = conn.Close() - }(conn) - - answer, err := D.RelayDnsPacket(pkt) - if err != nil { - return - } - _, _ = conn.WriteFrom(answer, addr) - }() -} - -func hijackTCPDns(conn net.Conn) { - go func() { - defer func(conn net.Conn) { - _ = conn.Close() - }(conn) - - if err := conn.SetDeadline(time.Now().Add(defaultDnsReadTimeout)); err != nil { - return - } - - for { - var length uint16 - if binary.Read(conn, binary.BigEndian, &length) != nil { - return - } - - data := make([]byte, length) - - _, err := io.ReadFull(conn, data) - if err != nil { - return - } - - rb, err := D.RelayDnsPacket(data) - if err != nil { - continue - } - - if binary.Write(conn, binary.BigEndian, uint16(len(rb))) != nil { - return - } - - if _, err = conn.Write(rb); err != nil { - return - } - } - }() -} - -type dnsHandler struct{} - -func newDnsHandler() golwip.DnsHandler { - return &dnsHandler{} -} - -func (d dnsHandler) ResolveIP(host string) (net.IP, error) { - log.Debugln("[TUN] lwip resolve ip for host: %s", host) - return resolver.ResolveIP(host) -} diff --git a/listener/tun/ipstack/lwip/tcp.go b/listener/tun/ipstack/lwip/tcp.go deleted file mode 100644 index c62a6beb..00000000 --- a/listener/tun/ipstack/lwip/tcp.go +++ /dev/null @@ -1,61 +0,0 @@ -package lwip - -import ( - "net" - "strconv" - - C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/context" - "github.com/Dreamacro/clash/log" - "github.com/yaling888/go-lwip" -) - -type tcpHandler struct { - dnsIP net.IP - tcpIn chan<- C.ConnContext -} - -func newTCPHandler(dnsIP net.IP, tcpIn chan<- C.ConnContext) golwip.TCPConnHandler { - return &tcpHandler{dnsIP, tcpIn} -} - -func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error { - if shouldHijackDns(h.dnsIP, target.IP, target.Port) { - hijackTCPDns(conn) - log.Debugln("[TUN] hijack dns tcp: %s:%d", target.IP.String(), target.Port) - return nil - } - - if conn.RemoteAddr() == nil { - _ = conn.Close() - return nil - } - - src, _ := conn.LocalAddr().(*net.TCPAddr) - dst, _ := conn.RemoteAddr().(*net.TCPAddr) - - addrType := C.AtypIPv4 - if dst.IP.To4() == nil { - addrType = C.AtypIPv6 - } - - metadata := &C.Metadata{ - NetWork: C.TCP, - Type: C.TUN, - SrcIP: src.IP, - DstIP: dst.IP, - SrcPort: strconv.Itoa(src.Port), - DstPort: strconv.Itoa(dst.Port), - AddrType: addrType, - Host: "", - } - - go func(conn net.Conn, metadata *C.Metadata) { - //if c, ok := conn.(*net.TCPConn); ok { - // c.SetKeepAlive(true) - //} - h.tcpIn <- context.NewConnContext(conn, metadata) - }(conn, metadata) - - return nil -} diff --git a/listener/tun/ipstack/lwip/tun.go b/listener/tun/ipstack/lwip/tun.go deleted file mode 100644 index 9037be6e..00000000 --- a/listener/tun/ipstack/lwip/tun.go +++ /dev/null @@ -1,121 +0,0 @@ -package lwip - -import ( - "io" - "net" - "sync" - - "github.com/Dreamacro/clash/adapter/inbound" - "github.com/Dreamacro/clash/common/pool" - "github.com/Dreamacro/clash/config" - C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/listener/tun/dev" - "github.com/Dreamacro/clash/listener/tun/ipstack" - "github.com/Dreamacro/clash/log" - "github.com/yaling888/go-lwip" -) - -type lwipAdapter struct { - device dev.TunDevice - lwipStack golwip.LWIPStack - lock sync.Mutex - mtu int - stackName string - dnsListen string - autoRoute bool -} - -func NewAdapter(device dev.TunDevice, conf config.Tun, mtu int, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.TunAdapter, error) { - adapter := &lwipAdapter{ - device: device, - mtu: mtu, - stackName: conf.Stack, - dnsListen: conf.DNSListen, - autoRoute: conf.AutoRoute, - } - - adapter.lock.Lock() - defer adapter.lock.Unlock() - - dnsHost, _, err := net.SplitHostPort(conf.DNSListen) - if err != nil { - return nil, err - } - - dnsIP := net.ParseIP(dnsHost) - - // Register output function, write packets from lwip stack to tun device - golwip.RegisterOutputFn(func(data []byte) (int, error) { - return device.Write(data) - }) - - // Set custom buffer pool - golwip.SetPoolAllocator(newLWIPPool()) - - // Setup TCP/IP stack. - lwipStack, err := golwip.NewLWIPStack(mtu) - if err != nil { - return nil, err - } - adapter.lwipStack = lwipStack - - golwip.RegisterDnsHandler(newDnsHandler()) - golwip.RegisterTCPConnHandler(newTCPHandler(dnsIP, tcpIn)) - golwip.RegisterUDPConnHandler(newUDPHandler(dnsIP, udpIn)) - - // Copy packets from tun device to lwip stack, it's the loop. - go func(lwipStack golwip.LWIPStack, device dev.TunDevice, mtu int) { - _, err := io.CopyBuffer(lwipStack.(io.Writer), device, make([]byte, mtu)) - if err != nil { - log.Debugln("copying data failed: %v", err) - } - }(lwipStack, device, mtu) - - return adapter, nil -} - -func (l *lwipAdapter) Stack() string { - return l.stackName -} - -func (l *lwipAdapter) AutoRoute() bool { - return l.autoRoute -} - -func (l *lwipAdapter) DNSListen() string { - return l.dnsListen -} - -func (l *lwipAdapter) Close() { - l.lock.Lock() - defer l.lock.Unlock() - - l.stopLocked() -} - -func (l *lwipAdapter) stopLocked() { - if l.lwipStack != nil { - _ = l.lwipStack.Close() - } - - if l.device != nil { - _ = l.device.Close() - } - - l.lwipStack = nil - l.device = nil -} - -type lwipPool struct{} - -func (p lwipPool) Get(size int) []byte { - return pool.Get(size) -} - -func (p lwipPool) Put(buf []byte) error { - return pool.Put(buf) -} - -func newLWIPPool() golwip.LWIPPool { - return &lwipPool{} -} diff --git a/listener/tun/ipstack/lwip/udp.go b/listener/tun/ipstack/lwip/udp.go deleted file mode 100644 index 747796bf..00000000 --- a/listener/tun/ipstack/lwip/udp.go +++ /dev/null @@ -1,74 +0,0 @@ -package lwip - -import ( - "io" - "net" - - "github.com/Dreamacro/clash/adapter/inbound" - C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/transport/socks5" - "github.com/yaling888/go-lwip" -) - -type udpPacket struct { - source *net.UDPAddr - payload []byte - sender golwip.UDPConn -} - -func (u *udpPacket) Data() []byte { - return u.payload -} - -func (u *udpPacket) WriteBack(b []byte, addr net.Addr) (n int, err error) { - _, ok := addr.(*net.UDPAddr) - if !ok { - return 0, io.ErrClosedPipe - } - - return u.sender.WriteFrom(b, u.source) -} - -func (u *udpPacket) Drop() { -} - -func (u *udpPacket) LocalAddr() net.Addr { - return u.source -} - -type udpHandler struct { - dnsIP net.IP - udpIn chan<- *inbound.PacketAdapter -} - -func newUDPHandler(dnsIP net.IP, udpIn chan<- *inbound.PacketAdapter) golwip.UDPConnHandler { - return &udpHandler{dnsIP, udpIn} -} - -func (h *udpHandler) Connect(golwip.UDPConn, *net.UDPAddr) error { - return nil -} - -func (h *udpHandler) ReceiveTo(conn golwip.UDPConn, data []byte, addr *net.UDPAddr) error { - if shouldHijackDns(h.dnsIP, addr.IP, addr.Port) { - hijackUDPDns(conn, data, addr) - log.Debugln("[TUN] hijack dns udp: %s:%d", addr.IP.String(), addr.Port) - return nil - } - - packet := &udpPacket{ - source: conn.LocalAddr(), - payload: data, - sender: conn, - } - - go func(addr *net.UDPAddr, packet *udpPacket) { - select { - case h.udpIn <- inbound.NewPacket(socks5.ParseAddrToSocksAddr(addr), packet, C.TUN): - default: - } - }(addr, packet) - - return nil -} diff --git a/listener/tun/tun_adapter.go b/listener/tun/tun_adapter.go index 9f1b69f6..ce771c42 100644 --- a/listener/tun/tun_adapter.go +++ b/listener/tun/tun_adapter.go @@ -11,7 +11,6 @@ import ( "github.com/Dreamacro/clash/listener/tun/dev" "github.com/Dreamacro/clash/listener/tun/ipstack" "github.com/Dreamacro/clash/listener/tun/ipstack/gvisor" - "github.com/Dreamacro/clash/listener/tun/ipstack/lwip" "github.com/Dreamacro/clash/listener/tun/ipstack/system" "github.com/Dreamacro/clash/log" ) @@ -34,9 +33,7 @@ func New(conf config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.Pack return nil, errors.New("unable to get device mtu") } - if strings.EqualFold(stack, "lwip") { - tunAdapter, err = lwip.NewAdapter(device, conf, mtu, tcpIn, udpIn) - } else if strings.EqualFold(stack, "system") { + if strings.EqualFold(stack, "system") { tunAdapter, err = system.NewAdapter(device, conf, mtu, tunAddress, tunAddress, func() {}, tcpIn, udpIn) } else if strings.EqualFold(stack, "gvisor") { tunAdapter, err = gvisor.NewAdapter(device, conf, tunAddress, tcpIn, udpIn)