mirror of
				https://github.com/xjasonlyu/tun2socks.git
				synced 2025-10-31 03:56:30 +08:00 
			
		
		
		
	remove ss & v2ray handler
This commit is contained in:
		| @@ -1,39 +0,0 @@ | ||||
| // +build shadowsocks | ||||
|  | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"net" | ||||
| 	"strings" | ||||
|  | ||||
| 	sscore "github.com/shadowsocks/go-shadowsocks2/core" | ||||
|  | ||||
| 	"github.com/xjasonlyu/tun2socks/common/log" | ||||
| 	"github.com/xjasonlyu/tun2socks/core" | ||||
| 	"github.com/xjasonlyu/tun2socks/proxy/shadowsocks" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	args.addFlag(fProxyServer) | ||||
| 	args.addFlag(fUdpTimeout) | ||||
|  | ||||
| 	args.ProxyCipher = flag.String("proxyCipher", "AEAD_CHACHA20_POLY1305", "Cipher used for Shadowsocks proxy, available ciphers: "+strings.Join(sscore.ListCipher(), " ")) | ||||
| 	args.ProxyPassword = flag.String("proxyPassword", "", "Password used for Shadowsocks proxy") | ||||
|  | ||||
| 	registerHandlerCreator("shadowsocks", func() { | ||||
| 		// Verify proxy server address. | ||||
| 		proxyAddr, err := net.ResolveTCPAddr("tcp", *args.ProxyServer) | ||||
| 		if err != nil { | ||||
| 			log.Fatalf("invalid proxy server address: %v", err) | ||||
| 		} | ||||
| 		proxyHost := proxyAddr.IP.String() | ||||
| 		proxyPort := uint16(proxyAddr.Port) | ||||
|  | ||||
| 		if *args.ProxyCipher == "" || *args.ProxyPassword == "" { | ||||
| 			log.Fatalf("invalid cipher or password") | ||||
| 		} | ||||
| 		core.RegisterTCPConnHandler(shadowsocks.NewTCPHandler(core.ParseTCPAddr(proxyHost, proxyPort).String(), *args.ProxyCipher, *args.ProxyPassword, fakeDns)) | ||||
| 		core.RegisterUDPConnHandler(shadowsocks.NewUDPHandler(core.ParseUDPAddr(proxyHost, proxyPort).String(), *args.ProxyCipher, *args.ProxyPassword, *args.UdpTimeout, dnsCache, fakeDns)) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,59 +0,0 @@ | ||||
| // +build v2ray | ||||
|  | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"flag" | ||||
| 	"io/ioutil" | ||||
| 	"strings" | ||||
|  | ||||
| 	vcore "v2ray.com/core" | ||||
| 	vproxyman "v2ray.com/core/app/proxyman" | ||||
| 	vbytespool "v2ray.com/core/common/bytespool" | ||||
|  | ||||
| 	"github.com/xjasonlyu/tun2socks/common/log" | ||||
| 	"github.com/xjasonlyu/tun2socks/core" | ||||
| 	"github.com/xjasonlyu/tun2socks/proxy/v2ray" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	args.addFlag(fUdpTimeout) | ||||
|  | ||||
| 	args.VConfig = flag.String("vconfig", "config.json", "Config file for v2ray, in JSON format, and note that routing in v2ray could not violate routes in the routing table") | ||||
| 	args.SniffingType = flag.String("sniffingType", "http,tls", "Enable domain sniffing for specific kind of traffic in v2ray") | ||||
|  | ||||
| 	registerHandlerCreator("v2ray", func() { | ||||
| 		core.SetBufferPool(vbytespool.GetPool(core.BufSize)) | ||||
|  | ||||
| 		configBytes, err := ioutil.ReadFile(*args.VConfig) | ||||
| 		if err != nil { | ||||
| 			log.Fatalf("invalid vconfig file") | ||||
| 		} | ||||
| 		var validSniffings []string | ||||
| 		sniffings := strings.Split(*args.SniffingType, ",") | ||||
| 		for _, s := range sniffings { | ||||
| 			if s == "http" || s == "tls" { | ||||
| 				validSniffings = append(validSniffings, s) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		v, err := vcore.StartInstance("json", configBytes) | ||||
| 		if err != nil { | ||||
| 			log.Fatalf("start V instance failed: %v", err) | ||||
| 		} | ||||
|  | ||||
| 		sniffingConfig := &vproxyman.SniffingConfig{ | ||||
| 			Enabled:             true, | ||||
| 			DestinationOverride: validSniffings, | ||||
| 		} | ||||
| 		if len(validSniffings) == 0 { | ||||
| 			sniffingConfig.Enabled = false | ||||
| 		} | ||||
|  | ||||
| 		ctx := vproxyman.ContextWithSniffingConfig(context.Background(), sniffingConfig) | ||||
|  | ||||
| 		core.RegisterTCPConnHandler(v2ray.NewTCPHandler(ctx, v)) | ||||
| 		core.RegisterUDPConnHandler(v2ray.NewUDPHandler(ctx, v, *args.UdpTimeout)) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,85 +0,0 @@ | ||||
| package shadowsocks | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
|  | ||||
| 	sscore "github.com/shadowsocks/go-shadowsocks2/core" | ||||
| 	sssocks "github.com/shadowsocks/go-shadowsocks2/socks" | ||||
|  | ||||
| 	"github.com/xjasonlyu/tun2socks/common/dns" | ||||
| 	"github.com/xjasonlyu/tun2socks/common/log" | ||||
| 	"github.com/xjasonlyu/tun2socks/core" | ||||
| ) | ||||
|  | ||||
| type tcpHandler struct { | ||||
| 	cipher  sscore.Cipher | ||||
| 	server  string | ||||
| 	fakeDns dns.FakeDns | ||||
| } | ||||
|  | ||||
| func (h *tcpHandler) handleInput(conn net.Conn, input io.ReadCloser) { | ||||
| 	defer func() { | ||||
| 		conn.Close() | ||||
| 		input.Close() | ||||
| 	}() | ||||
| 	io.Copy(conn, input) | ||||
| } | ||||
|  | ||||
| func (h *tcpHandler) handleOutput(conn net.Conn, output io.WriteCloser) { | ||||
| 	defer func() { | ||||
| 		conn.Close() | ||||
| 		output.Close() | ||||
| 	}() | ||||
| 	io.Copy(output, conn) | ||||
| } | ||||
|  | ||||
| func NewTCPHandler(server, cipher, password string, fakeDns dns.FakeDns) core.TCPConnHandler { | ||||
| 	ciph, err := sscore.PickCipher(cipher, []byte{}, password) | ||||
| 	if err != nil { | ||||
| 		log.Errorf("failed to pick a cipher: %v", err) | ||||
| 	} | ||||
| 	return &tcpHandler{ | ||||
| 		cipher:  ciph, | ||||
| 		server:  server, | ||||
| 		fakeDns: fakeDns, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error { | ||||
| 	if target == nil { | ||||
| 		log.Fatalf("unexpected nil target") | ||||
| 	} | ||||
|  | ||||
| 	// Connect the relay server. | ||||
| 	rc, err := net.Dial("tcp", h.server) | ||||
| 	if err != nil { | ||||
| 		return errors.New(fmt.Sprintf("dial remote server failed: %v", err)) | ||||
| 	} | ||||
| 	rc = h.cipher.StreamConn(rc) | ||||
|  | ||||
| 	// Replace with a domain name if target address IP is a fake IP. | ||||
| 	var targetHost string | ||||
| 	if h.fakeDns != nil && h.fakeDns.IsFakeIP(target.IP) { | ||||
| 		targetHost = h.fakeDns.QueryDomain(target.IP) | ||||
| 	} else { | ||||
| 		targetHost = target.IP.String() | ||||
| 	} | ||||
| 	dest := net.JoinHostPort(targetHost, strconv.Itoa(target.Port)) | ||||
|  | ||||
| 	// Write target address. | ||||
| 	tgt := sssocks.ParseAddr(dest) | ||||
| 	_, err = rc.Write(tgt) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("send target address failed: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	go h.handleInput(conn, rc) | ||||
| 	go h.handleOutput(conn, rc) | ||||
|  | ||||
| 	log.Infof("new proxy connection for target: %s:%s", target.Network(), dest) | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,172 +0,0 @@ | ||||
| package shadowsocks | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	sscore "github.com/shadowsocks/go-shadowsocks2/core" | ||||
| 	sssocks "github.com/shadowsocks/go-shadowsocks2/socks" | ||||
|  | ||||
| 	"github.com/xjasonlyu/tun2socks/common/dns" | ||||
| 	"github.com/xjasonlyu/tun2socks/common/log" | ||||
| 	"github.com/xjasonlyu/tun2socks/core" | ||||
| ) | ||||
|  | ||||
| type udpHandler struct { | ||||
| 	sync.Mutex | ||||
|  | ||||
| 	cipher     sscore.Cipher | ||||
| 	remoteAddr net.Addr | ||||
| 	conns      map[core.UDPConn]net.PacketConn | ||||
| 	dnsCache   dns.DnsCache | ||||
| 	fakeDns    dns.FakeDns | ||||
| 	timeout    time.Duration | ||||
| } | ||||
|  | ||||
| func NewUDPHandler(server, cipher, password string, timeout time.Duration, dnsCache dns.DnsCache, fakeDns dns.FakeDns) core.UDPConnHandler { | ||||
| 	ciph, err := sscore.PickCipher(cipher, []byte{}, password) | ||||
| 	if err != nil { | ||||
| 		log.Errorf("failed to pick a cipher: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	remoteAddr, err := net.ResolveUDPAddr("udp", server) | ||||
| 	if err != nil { | ||||
| 		log.Errorf("failed to resolve udp address: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	return &udpHandler{ | ||||
| 		cipher:     ciph, | ||||
| 		remoteAddr: remoteAddr, | ||||
| 		conns:      make(map[core.UDPConn]net.PacketConn, 16), | ||||
| 		dnsCache:   dnsCache, | ||||
| 		fakeDns:    fakeDns, | ||||
| 		timeout:    timeout, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) fetchUDPInput(conn core.UDPConn, input net.PacketConn) { | ||||
| 	buf := core.NewBytes(core.BufSize) | ||||
|  | ||||
| 	defer func() { | ||||
| 		h.Close(conn) | ||||
| 		core.FreeBytes(buf) | ||||
| 	}() | ||||
|  | ||||
| 	for { | ||||
| 		input.SetDeadline(time.Now().Add(h.timeout)) | ||||
| 		n, _, err := input.ReadFrom(buf) | ||||
| 		if err != nil { | ||||
| 			// log.Printf("read remote failed: %v", err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		addr := sssocks.SplitAddr(buf[:]) | ||||
| 		resolvedAddr, err := net.ResolveUDPAddr("udp", addr.String()) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		_, err = conn.WriteFrom(buf[int(len(addr)):n], resolvedAddr) | ||||
| 		if err != nil { | ||||
| 			log.Warnf("write local failed: %v", err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if h.dnsCache != nil { | ||||
| 			_, port, err := net.SplitHostPort(addr.String()) | ||||
| 			if err != nil { | ||||
| 				panic("impossible error") | ||||
| 			} | ||||
| 			if port == strconv.Itoa(dns.CommonDnsPort) { | ||||
| 				h.dnsCache.Store(buf[int(len(addr)):n]) | ||||
| 				return // DNS response | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) Connect(conn core.UDPConn, target *net.UDPAddr) error { | ||||
| 	pc, err := net.ListenPacket("udp", "") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	pc = h.cipher.PacketConn(pc) | ||||
|  | ||||
| 	h.Lock() | ||||
| 	h.conns[conn] = pc | ||||
| 	h.Unlock() | ||||
| 	go h.fetchUDPInput(conn, pc) | ||||
| 	if target != nil { | ||||
| 		log.Infof("new proxy connection for target: %s:%s", target.Network(), target.String()) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) ReceiveTo(conn core.UDPConn, data []byte, addr *net.UDPAddr) error { | ||||
| 	h.Lock() | ||||
| 	pc, ok1 := h.conns[conn] | ||||
| 	h.Unlock() | ||||
|  | ||||
| 	if addr.Port == dns.CommonDnsPort { | ||||
| 		if h.fakeDns != nil { | ||||
| 			resp, err := h.fakeDns.GenerateFakeResponse(data) | ||||
| 			if err == nil { | ||||
| 				_, err = conn.WriteFrom(resp, addr) | ||||
| 				if err != nil { | ||||
| 					return errors.New(fmt.Sprintf("write dns answer failed: %v", err)) | ||||
| 				} | ||||
| 				h.Close(conn) | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if h.dnsCache != nil { | ||||
| 			if answer := h.dnsCache.Query(data); answer != nil { | ||||
| 				_, err := conn.WriteFrom(answer, addr) | ||||
| 				if err != nil { | ||||
| 					return errors.New(fmt.Sprintf("cache dns answer failed: %v", err)) | ||||
| 				} | ||||
| 				h.Close(conn) | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if ok1 { | ||||
| 		// Replace with a domain name if target address IP is a fake IP. | ||||
| 		var targetHost string | ||||
| 		if h.fakeDns != nil && h.fakeDns.IsFakeIP(addr.IP) { | ||||
| 			targetHost = h.fakeDns.QueryDomain(addr.IP) | ||||
| 		} else { | ||||
| 			targetHost = addr.IP.String() | ||||
| 		} | ||||
| 		dest := net.JoinHostPort(targetHost, strconv.Itoa(addr.Port)) | ||||
|  | ||||
| 		buf := append([]byte{0, 0, 0}, sssocks.ParseAddr(dest)...) | ||||
| 		buf = append(buf, data[:]...) | ||||
| 		_, err := pc.WriteTo(buf[3:], h.remoteAddr) | ||||
| 		if err != nil { | ||||
| 			h.Close(conn) | ||||
| 			return errors.New(fmt.Sprintf("write remote failed: %v", err)) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} else { | ||||
| 		h.Close(conn) | ||||
| 		return errors.New(fmt.Sprintf("proxy connection %v->%v does not exists", conn.LocalAddr(), addr)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) Close(conn core.UDPConn) { | ||||
| 	conn.Close() | ||||
|  | ||||
| 	h.Lock() | ||||
| 	defer h.Unlock() | ||||
|  | ||||
| 	if pc, ok := h.conns[conn]; ok { | ||||
| 		pc.Close() | ||||
| 		delete(h.conns, conn) | ||||
| 	} | ||||
| } | ||||
| @@ -1,61 +0,0 @@ | ||||
| package v2ray | ||||
|  | ||||
| import ( | ||||
| 	// The following are necessary as they register handlers in their init functions. | ||||
|  | ||||
| 	// Required features. Can't remove unless there is replacements. | ||||
| 	_ "v2ray.com/core/app/dispatcher" | ||||
| 	_ "v2ray.com/core/app/proxyman/inbound" | ||||
| 	_ "v2ray.com/core/app/proxyman/outbound" | ||||
|  | ||||
| 	// Default commander and all its services. This is an optional feature. | ||||
| 	// _ "v2ray.com/core/app/commander" | ||||
| 	// _ "v2ray.com/core/app/log/command" | ||||
| 	// _ "v2ray.com/core/app/proxyman/command" | ||||
| 	// _ "v2ray.com/core/app/stats/command" | ||||
|  | ||||
| 	// Other optional features. | ||||
| 	_ "v2ray.com/core/app/dns" | ||||
| 	_ "v2ray.com/core/app/log" | ||||
| 	_ "v2ray.com/core/app/policy" | ||||
| 	_ "v2ray.com/core/app/router" | ||||
| 	_ "v2ray.com/core/app/stats" | ||||
|  | ||||
| 	// Inbound and outbound proxies. | ||||
| 	_ "v2ray.com/core/proxy/blackhole" | ||||
| 	_ "v2ray.com/core/proxy/dokodemo" | ||||
| 	_ "v2ray.com/core/proxy/freedom" | ||||
| 	_ "v2ray.com/core/proxy/http" | ||||
| 	_ "v2ray.com/core/proxy/mtproto" | ||||
| 	_ "v2ray.com/core/proxy/shadowsocks" | ||||
| 	_ "v2ray.com/core/proxy/socks" | ||||
| 	_ "v2ray.com/core/proxy/vmess/inbound" | ||||
| 	_ "v2ray.com/core/proxy/vmess/outbound" | ||||
|  | ||||
| 	// Transports | ||||
| 	_ "v2ray.com/core/transport/internet/domainsocket" | ||||
| 	_ "v2ray.com/core/transport/internet/http" | ||||
| 	_ "v2ray.com/core/transport/internet/kcp" | ||||
| 	_ "v2ray.com/core/transport/internet/quic" | ||||
| 	_ "v2ray.com/core/transport/internet/tcp" | ||||
| 	_ "v2ray.com/core/transport/internet/tls" | ||||
| 	_ "v2ray.com/core/transport/internet/udp" | ||||
| 	_ "v2ray.com/core/transport/internet/websocket" | ||||
|  | ||||
| 	// Transport headers | ||||
| 	_ "v2ray.com/core/transport/internet/headers/http" | ||||
| 	_ "v2ray.com/core/transport/internet/headers/noop" | ||||
| 	_ "v2ray.com/core/transport/internet/headers/srtp" | ||||
| 	_ "v2ray.com/core/transport/internet/headers/tls" | ||||
| 	_ "v2ray.com/core/transport/internet/headers/utp" | ||||
| 	_ "v2ray.com/core/transport/internet/headers/wechat" | ||||
| 	_ "v2ray.com/core/transport/internet/headers/wireguard" | ||||
|  | ||||
| 	// JSON config support. Choose only one from the two below. | ||||
| 	// The following line loads JSON from v2ctl | ||||
| 	// _ "v2ray.com/core/main/json" | ||||
| 	// The following line loads JSON internally | ||||
| 	_ "v2ray.com/core/main/jsonem" | ||||
| 	// Load config from file or http(s) | ||||
| 	// _ "v2ray.com/core/main/confloader/external" | ||||
| ) | ||||
| @@ -1,14 +0,0 @@ | ||||
| // +build !ios,!android | ||||
|  | ||||
| package v2ray | ||||
|  | ||||
| import ( | ||||
| 	_ "v2ray.com/core/app/commander" | ||||
| 	_ "v2ray.com/core/app/log/command" | ||||
| 	_ "v2ray.com/core/app/proxyman/command" | ||||
| 	_ "v2ray.com/core/app/stats/command" | ||||
|  | ||||
| 	_ "v2ray.com/core/app/reverse" | ||||
|  | ||||
| 	_ "v2ray.com/core/transport/internet/domainsocket" | ||||
| ) | ||||
| @@ -1,58 +0,0 @@ | ||||
| package v2ray | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
|  | ||||
| 	vcore "v2ray.com/core" | ||||
| 	vnet "v2ray.com/core/common/net" | ||||
| 	vsession "v2ray.com/core/common/session" | ||||
|  | ||||
| 	"github.com/xjasonlyu/tun2socks/common/log" | ||||
| 	"github.com/xjasonlyu/tun2socks/core" | ||||
| ) | ||||
|  | ||||
| type tcpHandler struct { | ||||
| 	ctx context.Context | ||||
| 	v   *vcore.Instance | ||||
| } | ||||
|  | ||||
| func (h *tcpHandler) handleInput(conn net.Conn, input io.ReadCloser) { | ||||
| 	defer func() { | ||||
| 		conn.Close() | ||||
| 		input.Close() | ||||
| 	}() | ||||
| 	io.Copy(conn, input) | ||||
| } | ||||
|  | ||||
| func (h *tcpHandler) handleOutput(conn net.Conn, output io.WriteCloser) { | ||||
| 	defer func() { | ||||
| 		conn.Close() | ||||
| 		output.Close() | ||||
| 	}() | ||||
| 	io.Copy(output, conn) | ||||
| } | ||||
|  | ||||
| func NewTCPHandler(ctx context.Context, instance *vcore.Instance) core.TCPConnHandler { | ||||
| 	return &tcpHandler{ | ||||
| 		ctx: ctx, | ||||
| 		v:   instance, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *tcpHandler) Handle(conn net.Conn, target *net.TCPAddr) error { | ||||
| 	dest := vnet.DestinationFromAddr(target) | ||||
| 	sid := vsession.NewID() | ||||
| 	ctx := vsession.ContextWithID(h.ctx, sid) | ||||
| 	c, err := vcore.Dial(ctx, h.v, dest) | ||||
| 	if err != nil { | ||||
| 		return errors.New(fmt.Sprintf("dial V proxy connection failed: %v", err)) | ||||
| 	} | ||||
| 	go h.handleInput(conn, c) | ||||
| 	go h.handleOutput(conn, c) | ||||
| 	log.Infof("new proxy connection for target: %s:%s", target.Network(), target.String()) | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,138 +0,0 @@ | ||||
| package v2ray | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	vcore "v2ray.com/core" | ||||
| 	vsession "v2ray.com/core/common/session" | ||||
| 	vsignal "v2ray.com/core/common/signal" | ||||
| 	vtask "v2ray.com/core/common/task" | ||||
|  | ||||
| 	"github.com/xjasonlyu/tun2socks/common/log" | ||||
| 	"github.com/xjasonlyu/tun2socks/core" | ||||
| ) | ||||
|  | ||||
| type udpConnEntry struct { | ||||
| 	conn net.PacketConn | ||||
|  | ||||
| 	// `ReadFrom` method of PacketConn given by V2Ray | ||||
| 	// won't return the correct remote address, we treat | ||||
| 	// all data receive from V2Ray are coming from the | ||||
| 	// same remote host, i.e. the `target` that passed | ||||
| 	// to `Connect`. | ||||
| 	target *net.UDPAddr | ||||
|  | ||||
| 	updater vsignal.ActivityUpdater | ||||
| } | ||||
|  | ||||
| type udpHandler struct { | ||||
| 	sync.Mutex | ||||
|  | ||||
| 	ctx     context.Context | ||||
| 	v       *vcore.Instance | ||||
| 	conns   map[core.UDPConn]*udpConnEntry | ||||
| 	timeout time.Duration // Maybe override by V2Ray local policies for some conns. | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) fetchInput(conn core.UDPConn) { | ||||
| 	h.Lock() | ||||
| 	c, ok := h.conns[conn] | ||||
| 	h.Unlock() | ||||
| 	if !ok { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	buf := core.NewBytes(core.BufSize) | ||||
| 	defer core.FreeBytes(buf) | ||||
|  | ||||
| 	for { | ||||
| 		n, _, err := c.conn.ReadFrom(buf) | ||||
| 		if err != nil && n <= 0 { | ||||
| 			h.Close(conn) | ||||
| 			conn.Close() | ||||
| 			return | ||||
| 		} | ||||
| 		c.updater.Update() | ||||
| 		_, err = conn.WriteFrom(buf[:n], c.target) | ||||
| 		if err != nil { | ||||
| 			h.Close(conn) | ||||
| 			conn.Close() | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func NewUDPHandler(ctx context.Context, instance *vcore.Instance, timeout time.Duration) core.UDPConnHandler { | ||||
| 	return &udpHandler{ | ||||
| 		ctx:     ctx, | ||||
| 		v:       instance, | ||||
| 		conns:   make(map[core.UDPConn]*udpConnEntry, 16), | ||||
| 		timeout: timeout, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) Connect(conn core.UDPConn, target *net.UDPAddr) error { | ||||
| 	if target == nil { | ||||
| 		return errors.New("nil target is not allowed") | ||||
| 	} | ||||
| 	sid := vsession.NewID() | ||||
| 	ctx := vsession.ContextWithID(h.ctx, sid) | ||||
| 	ctx, cancel := context.WithCancel(ctx) | ||||
| 	pc, err := vcore.DialUDP(ctx, h.v) | ||||
| 	if err != nil { | ||||
| 		return errors.New(fmt.Sprintf("dial V proxy connection failed: %v", err)) | ||||
| 	} | ||||
| 	timer := vsignal.CancelAfterInactivity(ctx, cancel, h.timeout) | ||||
| 	h.Lock() | ||||
| 	h.conns[conn] = &udpConnEntry{ | ||||
| 		conn:    pc, | ||||
| 		target:  target, | ||||
| 		updater: timer, | ||||
| 	} | ||||
| 	h.Unlock() | ||||
| 	fetchTask := func() error { | ||||
| 		h.fetchInput(conn) | ||||
| 		return nil | ||||
| 	} | ||||
| 	go func() { | ||||
| 		if err := vtask.Run(ctx, fetchTask); err != nil { | ||||
| 			pc.Close() | ||||
| 		} | ||||
| 	}() | ||||
| 	log.Infof("new proxy connection for target: %s:%s", target.Network(), target.String()) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) ReceiveTo(conn core.UDPConn, data []byte, addr *net.UDPAddr) error { | ||||
| 	h.Lock() | ||||
| 	c, ok := h.conns[conn] | ||||
| 	h.Unlock() | ||||
|  | ||||
| 	if ok { | ||||
| 		_, err := c.conn.WriteTo(data, addr) | ||||
| 		c.updater.Update() | ||||
| 		if err != nil { | ||||
| 			h.Close(conn) | ||||
| 			return errors.New(fmt.Sprintf("write remote failed: %v", err)) | ||||
| 		} | ||||
| 		return nil | ||||
| 	} else { | ||||
| 		h.Close(conn) | ||||
| 		return errors.New(fmt.Sprintf("proxy connection %v->%v does not exists", conn.LocalAddr(), c.target)) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (h *udpHandler) Close(conn core.UDPConn) { | ||||
| 	h.Lock() | ||||
| 	defer h.Unlock() | ||||
|  | ||||
| 	if c, found := h.conns[conn]; found { | ||||
| 		c.conn.Close() | ||||
| 	} | ||||
| 	delete(h.conns, conn) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Jason
					Jason