using sing-tun instead of tun2socket

This commit is contained in:
wwqgtxx 2024-09-10 16:23:12 +08:00
parent 4df39342a2
commit 158e47b372
7 changed files with 23 additions and 227 deletions

View File

@ -3,10 +3,8 @@ module cfa
go 1.20 go 1.20
require ( require (
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34
github.com/dlclark/regexp2 v1.11.4 github.com/dlclark/regexp2 v1.11.4
github.com/metacubex/mihomo v1.7.0 github.com/metacubex/mihomo v1.7.0
github.com/miekg/dns v1.1.62
github.com/oschwald/maxminddb-golang v1.12.0 github.com/oschwald/maxminddb-golang v1.12.0
golang.org/x/sync v0.8.0 golang.org/x/sync v0.8.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
@ -68,6 +66,7 @@ require (
github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd // indirect github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd // indirect
github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 // indirect github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 // indirect
github.com/metacubex/utls v1.6.6 // indirect github.com/metacubex/utls v1.6.6 // indirect
github.com/miekg/dns v1.1.62 // indirect
github.com/mroth/weightedrand/v2 v2.1.0 // indirect github.com/mroth/weightedrand/v2 v2.1.0 // indirect
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
github.com/onsi/ginkgo/v2 v2.9.5 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect

View File

@ -1,7 +1,5 @@
github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08= github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08=
github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY= github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY=
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34 h1:USCTqih5d1bUXUxWNS9ZD5Tx/lb0jXHEtRIIx/F9dMc=
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34/go.mod h1:YR9wK13TgI5ww8iKWm91MHiSoHC7Oz0U4beCCmtXqLw=
github.com/RyuaNerin/elliptic2 v1.0.0/go.mod h1:wWB8fWrJI/6EPJkyV/r1Rj0hxUgrusmqSj8JN6yNf/A= github.com/RyuaNerin/elliptic2 v1.0.0/go.mod h1:wWB8fWrJI/6EPJkyV/r1Rj0hxUgrusmqSj8JN6yNf/A=
github.com/RyuaNerin/go-krypto v1.2.4 h1:mXuNdK6M317aPV0llW6Xpjbo4moOlPF7Yxz4tb4b4Go= github.com/RyuaNerin/go-krypto v1.2.4 h1:mXuNdK6M317aPV0llW6Xpjbo4moOlPF7Yxz4tb4b4Go=
github.com/RyuaNerin/go-krypto v1.2.4/go.mod h1:QqCYkoutU3yInyD9INt2PGolVRsc3W4oraQadVGXJ/8= github.com/RyuaNerin/go-krypto v1.2.4/go.mod h1:QqCYkoutU3yInyD9INt2PGolVRsc3W4oraQadVGXJ/8=

View File

@ -9,6 +9,7 @@ import (
"github.com/dlclark/regexp2" "github.com/dlclark/regexp2"
"cfa/native/common" "cfa/native/common"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
@ -21,6 +22,7 @@ var processors = []processor{
patchGeneral, patchGeneral,
patchProfile, patchProfile,
patchDns, patchDns,
patchTun,
patchProviders, patchProviders,
validConfig, validConfig,
} }
@ -74,6 +76,12 @@ func patchDns(cfg *config.RawConfig, _ string) error {
return nil return nil
} }
func patchTun(cfg *config.RawConfig, _ string) error {
cfg.Tun.Enable = false
return nil
}
func patchProviders(cfg *config.RawConfig, profileDir string) error { func patchProviders(cfg *config.RawConfig, profileDir string) error {
forEachProviders(cfg, func(index int, total int, key string, provider map[string]any) { forEachProviders(cfg, func(index int, total int, key string, provider map[string]any) {
if path, ok := provider["path"].(string); ok { if path, ok := provider["path"].(string); ok {

View File

@ -1,33 +0,0 @@
package tun
import (
"net"
"github.com/metacubex/mihomo/dns"
D "github.com/miekg/dns"
)
func shouldHijackDns(dns net.IP, target net.IP, targetPort int) bool {
if targetPort != 53 {
return false
}
return net.IPv4zero.Equal(dns) || target.Equal(dns)
}
func relayDns(payload []byte) ([]byte, error) {
msg := &D.Msg{}
if err := msg.Unpack(payload); err != nil {
return nil, err
}
r, err := dns.ServeDNSWithDefaultServer(msg)
if err != nil {
return nil, err
}
r.SetRcode(msg, r.Rcode)
return r.Pack()
}

View File

@ -1,21 +0,0 @@
package tun
import (
"net"
C "github.com/metacubex/mihomo/constant"
)
func createMetadata(lAddr, rAddr *net.TCPAddr) *C.Metadata {
return &C.Metadata{
NetWork: C.TCP,
Type: C.SOCKS5,
SrcIP: lAddr.AddrPort().Addr(),
DstIP: rAddr.AddrPort().Addr(),
SrcPort: uint16(lAddr.Port),
DstPort: uint16(rAddr.Port),
Host: "",
RawSrcAddr: lAddr,
RawDstAddr: rAddr,
}
}

View File

@ -1,161 +1,34 @@
package tun package tun
import ( import (
"encoding/binary"
"io" "io"
"net" "net/netip"
"os"
"time"
"github.com/Kr328/tun2socket"
"github.com/metacubex/mihomo/adapter/inbound"
"github.com/metacubex/mihomo/common/pool"
C "github.com/metacubex/mihomo/constant" C "github.com/metacubex/mihomo/constant"
LC "github.com/metacubex/mihomo/listener/config"
"github.com/metacubex/mihomo/listener/sing_tun"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/transport/socks5"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
) )
var _, ipv4LoopBack, _ = net.ParseCIDR("127.0.0.0/8")
func Start(fd int, gateway, portal, dns string) (io.Closer, error) { func Start(fd int, gateway, portal, dns string) (io.Closer, error) {
log.Debugln("TUN: fd = %d, gateway = %s, portal = %s, dns = %s", fd, gateway, portal, dns) log.Debugln("TUN: fd = %d, gateway = %s, portal = %s, dns = %s", fd, gateway, portal, dns)
device := os.NewFile(uintptr(fd), "/dev/tun") options := LC.Tun{
Enable: true,
ip, network, err := net.ParseCIDR(gateway) Device: sing_tun.InterfaceName,
if err != nil { Stack: C.TunSystem,
panic(err.Error()) DNSHijack: []string{dns + ":53"}, // "172.19.0.2" or "0.0.0.0"
} else { Inet4Address: []netip.Prefix{netip.MustParsePrefix(gateway)}, // "172.19.0.1/30"
network.IP = ip MTU: 9000, // private const val TUN_MTU = 9000 in TunService.kt
FileDescriptor: fd,
} }
stack, err := tun2socket.StartTun2Socket(device, network, net.ParseIP(portal)) listener, err := sing_tun.New(options, tunnel.Tunnel)
if err != nil { if err != nil {
_ = device.Close() log.Errorln("TUN:", err)
return nil, err return nil, err
} }
dnsAddr := net.ParseIP(dns) return listener, nil
tcp := func() {
defer stack.TCP().Close()
defer log.Debugln("TCP: closed")
for stack.TCP().SetDeadline(time.Time{}) == nil {
conn, err := stack.TCP().Accept()
if err != nil {
log.Debugln("Accept connection: %v", err)
continue
}
lAddr := conn.LocalAddr().(*net.TCPAddr)
rAddr := conn.RemoteAddr().(*net.TCPAddr)
if ipv4LoopBack.Contains(rAddr.IP) {
conn.Close()
continue
}
if shouldHijackDns(dnsAddr, rAddr.IP, rAddr.Port) {
go func() {
defer conn.Close()
buf := pool.Get(pool.UDPBufferSize)
defer pool.Put(buf)
for {
conn.SetReadDeadline(time.Now().Add(C.DefaultTCPTimeout))
length := uint16(0)
if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
return
}
if int(length) > len(buf) {
return
}
n, err := conn.Read(buf[:length])
if err != nil {
return
}
msg, err := relayDns(buf[:n])
if err != nil {
return
}
_, _ = conn.Write(msg)
}
}()
continue
}
go tunnel.Tunnel.HandleTCPConn(conn, createMetadata(lAddr, rAddr))
}
}
udp := func() {
defer stack.UDP().Close()
defer log.Debugln("UDP: closed")
for {
buf := pool.Get(pool.UDPBufferSize)
n, lRAddr, rRAddr, err := stack.UDP().ReadFrom(buf)
if err != nil {
return
}
raw := buf[:n]
lAddr := lRAddr.(*net.UDPAddr)
rAddr := rRAddr.(*net.UDPAddr)
if ipv4LoopBack.Contains(rAddr.IP) {
pool.Put(buf)
continue
}
if shouldHijackDns(dnsAddr, rAddr.IP, rAddr.Port) {
go func() {
defer pool.Put(buf)
msg, err := relayDns(raw)
if err != nil {
return
}
_, _ = stack.UDP().WriteTo(msg, rAddr, lAddr)
}()
continue
}
pkt := &packet{
local: lAddr,
data: raw,
writeBack: func(b []byte, addr net.Addr) (int, error) {
return stack.UDP().WriteTo(b, addr, lAddr)
},
drop: func() {
pool.Put(buf)
},
}
tunnel.Tunnel.HandleUDPPacket(inbound.NewPacket(socks5.ParseAddrToSocksAddr(rAddr), pkt, C.SOCKS5))
}
}
go tcp()
go udp()
go udp()
return stack, nil
} }

View File

@ -1,28 +0,0 @@
package tun
import (
"net"
)
type packet struct {
local *net.UDPAddr
data []byte
writeBack func(b []byte, addr net.Addr) (int, error)
drop func()
}
func (pkt *packet) Data() []byte {
return pkt.data
}
func (pkt *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) {
return pkt.writeBack(b, addr)
}
func (pkt *packet) Drop() {
pkt.drop()
}
func (pkt *packet) LocalAddr() net.Addr {
return pkt.local
}