mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-11-10 21:21:02 +08:00
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
package adapter
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
"sync/atomic"
|
|
|
|
"github.com/sagernet/sing-box/log"
|
|
"github.com/sagernet/sing-tun"
|
|
"github.com/sagernet/sing-tun/gtcpip/header"
|
|
"github.com/sagernet/sing/common/byteformats"
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
N "github.com/sagernet/sing/common/network"
|
|
)
|
|
|
|
func JudgeHostFlow(ctx context.Context, networkManager NetworkManager, logger log.ContextLogger, network uint8, source netip.AddrPort, destination netip.AddrPort) tun.FlowVerdict {
|
|
port := networkManager.HostPort()
|
|
if port == nil {
|
|
return tun.FlowVerdict{Action: tun.ActionAccept}
|
|
}
|
|
inet4Address, inet6Address := port.PortAddresses()
|
|
hostAddress := inet4Address
|
|
if destination.Addr().Is6() {
|
|
hostAddress = inet6Address
|
|
}
|
|
networkName := flowNetworkName(network)
|
|
if !hostAddress.IsValid() || networkName == "" {
|
|
return tun.FlowVerdict{Action: tun.ActionAccept}
|
|
}
|
|
hostDestination := netip.AddrPortFrom(hostAddress, destination.Port())
|
|
return tun.FlowVerdict{
|
|
Action: tun.ActionFlow,
|
|
Port: port,
|
|
Destination: hostDestination,
|
|
NewTracker: func() tun.FlowTracker {
|
|
flowContext := log.ContextWithNewID(ctx)
|
|
sourceAddress := M.SocksaddrFromNetIP(source)
|
|
destinationAddress := M.SocksaddrFromNetIP(hostDestination)
|
|
if networkName == N.NetworkICMP {
|
|
sourceAddress.Port = 0
|
|
destinationAddress.Port = 0
|
|
}
|
|
logger.InfoContext(flowContext, "forward ", networkName, " connection from ", sourceAddress, " to ", destinationAddress, " via tun")
|
|
return NewFlowLogger(flowContext, logger)
|
|
},
|
|
}
|
|
}
|
|
|
|
func flowNetworkName(network uint8) string {
|
|
switch network {
|
|
case uint8(header.TCPProtocolNumber):
|
|
return N.NetworkTCP
|
|
case uint8(header.UDPProtocolNumber):
|
|
return N.NetworkUDP
|
|
case uint8(header.ICMPv4ProtocolNumber), uint8(header.ICMPv6ProtocolNumber):
|
|
return N.NetworkICMP
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
var _ tun.FlowTracker = (*FlowLogger)(nil)
|
|
|
|
type FlowLogger struct {
|
|
ctx context.Context
|
|
logger log.ContextLogger
|
|
upload atomic.Int64
|
|
download atomic.Int64
|
|
}
|
|
|
|
func NewFlowLogger(ctx context.Context, logger log.ContextLogger) *FlowLogger {
|
|
return &FlowLogger{ctx: ctx, logger: logger}
|
|
}
|
|
|
|
func (l *FlowLogger) AttachFlow(handle tun.FlowHandle) {
|
|
}
|
|
|
|
func (l *FlowLogger) CountForward(n int) {
|
|
l.upload.Add(int64(n))
|
|
}
|
|
|
|
func (l *FlowLogger) CountReverse(n int) {
|
|
l.download.Add(int64(n))
|
|
}
|
|
|
|
func (l *FlowLogger) FlowEstablished() {
|
|
}
|
|
|
|
func (l *FlowLogger) CloseFlow(reason tun.FlowCloseReason) {
|
|
l.logger.DebugContext(l.ctx, "flow closed: ", reason,
|
|
", upload ", byteformats.FormatBytes(uint64(l.upload.Load())), ", download ", byteformats.FormatBytes(uint64(l.download.Load())))
|
|
}
|