rename vtun to tungo

This commit is contained in:
ginuerzh
2025-07-26 16:17:04 +08:00
parent 281295d02f
commit 35a049fb03
30 changed files with 801 additions and 307 deletions
+4 -4
View File
@@ -98,7 +98,7 @@ func (d *Dialer) Dial(ctx context.Context, network, addr string) (conn net.Conn,
return
}
log.Debugf("dial %s %v@%s failed: %s", network, ifAddr, ifceName, err)
log.Debugf("dial %s/%s via interface %s@%v failed: %s", addr, network, ifceName, ifAddr, err)
if strict &&
!strings.Contains(err.Error(), "no suitable address found") &&
@@ -113,7 +113,7 @@ func (d *Dialer) Dial(ctx context.Context, network, addr string) (conn net.Conn,
func (d *Dialer) dialOnce(ctx context.Context, network, addr, ifceName string, ifAddr net.Addr, log logger.Logger) (net.Conn, error) {
if ifceName != "" {
log.Debugf("interface: %s %v/%s", ifceName, ifAddr, network)
log.Debugf("dial %s/%s via interface %s@%s", addr, network, ifceName, ifAddr)
}
switch network {
@@ -135,7 +135,7 @@ func (d *Dialer) dialOnce(ctx context.Context, network, addr, ifceName string, i
}
err = sc.Control(func(fd uintptr) {
if ifceName != "" {
if err := bindDevice(fd, ifceName); err != nil {
if err := bindDevice(network, fd, ifceName); err != nil {
log.Warnf("bind device: %v", err)
}
}
@@ -159,7 +159,7 @@ func (d *Dialer) dialOnce(ctx context.Context, network, addr, ifceName string, i
Control: func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
if ifceName != "" {
if err := bindDevice(fd, ifceName); err != nil {
if err := bindDevice(network, fd, ifceName); err != nil {
log.Warnf("bind device: %v", err)
}
}
+32
View File
@@ -0,0 +1,32 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func bindDevice(network string, fd uintptr, ifceName string) error {
if ifceName == "" {
return nil
}
ifce, err := net.InterfaceByName(ifceName)
if err == nil {
return err
}
switch network {
case "tcp", "tcp4", "udp4":
return unix.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, ifce.Index)
case "tcp6", "udp6":
return unix.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_BOUND_IF, ifce.Index)
}
return nil
}
func setMark(fd uintptr, mark int) error {
return nil
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"golang.org/x/sys/unix"
)
func bindDevice(fd uintptr, ifceName string) error {
func bindDevice(network string, fd uintptr, ifceName string) error {
if ifceName == "" {
return nil
}
+2 -2
View File
@@ -1,8 +1,8 @@
//go:build !linux
//go:build !linux && !windows && !darwin
package dialer
func bindDevice(fd uintptr, ifceName string) error {
func bindDevice(network string, fd uintptr, ifceName string) error {
return nil
}
+51
View File
@@ -0,0 +1,51 @@
package dialer
import (
"encoding/binary"
"net"
"unsafe"
"golang.org/x/sys/windows"
)
const (
IP_UNICAST_IF = 31
IPV6_UNICAST_IF = 31
)
func bindDevice(network string, fd uintptr, ifceName string) error {
if ifceName == "" {
return nil
}
ifce, err := net.InterfaceByName(ifceName)
if err == nil {
return err
}
switch network {
case "tcp", "tcp4", "udp4":
return bindSocketToInterface4(windows.Handle(fd), uint32(ifce.Index))
case "tcp6", "udp6":
return bindSocketToInterface6(windows.Handle(fd), uint32(ifce.Index))
}
return nil
}
func setMark(fd uintptr, mark int) error {
return nil
}
func bindSocketToInterface4(handle windows.Handle, index uint32) error {
// For IPv4, this parameter must be an interface index in network byte order.
// Ref: https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
var bytes [4]byte
binary.BigEndian.PutUint32(bytes[:], index)
index = *(*uint32)(unsafe.Pointer(&bytes[0]))
return windows.SetsockoptInt(handle, windows.IPPROTO_IP, IP_UNICAST_IF, int(index))
}
func bindSocketToInterface6(handle windows.Handle, index uint32) error {
return windows.SetsockoptInt(handle, windows.IPPROTO_IPV6, IPV6_UNICAST_IF, int(index))
}
+12
View File
@@ -42,6 +42,10 @@ import (
"golang.org/x/time/rate"
)
const (
DefaultReadTimeout = 30 * time.Second
)
var (
DefaultCertPool = tls_util.NewMemoryCertPool()
)
@@ -124,6 +128,10 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO
opt(&ho)
}
if h.ReadTimeout <= 0 {
h.ReadTimeout = DefaultReadTimeout
}
pStats := xstats.Stats{}
conn = stats_wrapper.WrapConn(conn, &pStats)
@@ -769,6 +777,10 @@ func (h *Sniffer) HandleTLS(ctx context.Context, conn net.Conn, opts ...HandleOp
opt(&ho)
}
if h.ReadTimeout <= 0 {
h.ReadTimeout = DefaultReadTimeout
}
buf := new(bytes.Buffer)
clientHello, err := dissector.ParseClientHello(io.TeeReader(conn, buf))
if err != nil {
+10
View File
@@ -39,6 +39,8 @@ import (
)
const (
DefaultReadTimeout = 30 * time.Second
// DefaultBodySize is the default HTTP body or websocket frame size to record.
DefaultBodySize = 64 * 1024 // 64KB
// MaxBodySize is the maximum HTTP body or websocket frame size to record.
@@ -115,6 +117,10 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO
opt(&ho)
}
if h.ReadTimeout <= 0 {
h.ReadTimeout = DefaultReadTimeout
}
pStats := xstats.Stats{}
conn = stats_wrapper.WrapConn(conn, &pStats)
@@ -570,6 +576,10 @@ func (h *Sniffer) HandleTLS(ctx context.Context, conn net.Conn, opts ...HandleOp
opt(&ho)
}
if h.ReadTimeout <= 0 {
h.ReadTimeout = DefaultReadTimeout
}
buf := new(bytes.Buffer)
clientHello, err := dissector.ParseClientHello(io.TeeReader(conn, buf))
if err != nil {
+8
View File
@@ -24,6 +24,10 @@ func NewHandlerStats(service string, resetTraffic bool) *HandlerStats {
}
func (p *HandlerStats) Stats(client string) stats.Stats {
if p == nil {
return nil
}
p.mu.RLock()
pstats := p.stats[client]
p.mu.RUnlock()
@@ -43,6 +47,10 @@ func (p *HandlerStats) Stats(client string) stats.Stats {
}
func (p *HandlerStats) Events() (events []observer.Event) {
if p == nil {
return
}
p.mu.RLock()
defer p.mu.RUnlock()