Refactor UDP DNS hijack
This commit is contained in:
@@ -420,6 +420,10 @@ func (e *Endpoint) JudgeFlow(network uint8, source netip.AddrPort, destination n
|
||||
return judgeOpenConnectFlow(e.router, e.Tag(), e.Type(), e.state.Load().localAddresses, network, source, destination, firstPacket)
|
||||
}
|
||||
|
||||
func (e *Endpoint) NewDNSPacket(payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
e.newDNSPacket(log.ContextWithNewID(e.loopContext), e, payload, source, destination, writer)
|
||||
}
|
||||
|
||||
func (e *Endpoint) ready() bool {
|
||||
state := e.state.Load()
|
||||
return state.started && state.tunnelConfigured
|
||||
|
||||
@@ -68,6 +68,18 @@ func (e *endpointBase) newPacketConnection(ctx context.Context, endpoint adapter
|
||||
e.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
|
||||
}
|
||||
|
||||
func (e *endpointBase) newDNSPacket(ctx context.Context, endpoint adapter.Endpoint, payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
var metadata adapter.InboundContext
|
||||
metadata.Inbound = endpoint.Tag()
|
||||
metadata.InboundType = endpoint.Type()
|
||||
metadata.Network = N.NetworkUDP
|
||||
metadata.Source = source
|
||||
metadata.Destination = destination
|
||||
metadata.Protocol = C.ProtocolDNS
|
||||
e.logger.InfoContext(ctx, "inbound DNS packet from ", source)
|
||||
e.router.HijackDNSPacket(ctx, payload, writer, metadata)
|
||||
}
|
||||
|
||||
func isEndpointLocalAddress(localAddresses []netip.Prefix, address netip.Addr) bool {
|
||||
for _, localPrefix := range localAddresses {
|
||||
if address == localPrefix.Addr() {
|
||||
|
||||
@@ -477,6 +477,10 @@ func (c *ClientEndpoint) JudgeFlow(network uint8, source netip.AddrPort, destina
|
||||
return judgeOpenVPNFlow(c.router, c.Tag(), c.Type(), c.state.Load().localAddresses, network, source, destination, firstPacket)
|
||||
}
|
||||
|
||||
func (c *ClientEndpoint) NewDNSPacket(payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
c.newDNSPacket(log.ContextWithNewID(c.ctx), c, payload, source, destination, writer)
|
||||
}
|
||||
|
||||
func (c *ClientEndpoint) ready() bool {
|
||||
state := c.state.Load()
|
||||
return state.started && state.tunnelConfigured
|
||||
|
||||
@@ -72,6 +72,18 @@ func (e *endpointBase) newPacketConnection(ctx context.Context, endpoint adapter
|
||||
e.router.RoutePacketConnectionEx(ctx, conn, metadata, onClose)
|
||||
}
|
||||
|
||||
func (e *endpointBase) newDNSPacket(ctx context.Context, endpoint adapter.Endpoint, payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
var metadata adapter.InboundContext
|
||||
metadata.Inbound = endpoint.Tag()
|
||||
metadata.InboundType = endpoint.Type()
|
||||
metadata.Network = N.NetworkUDP
|
||||
metadata.Source = source
|
||||
metadata.Destination = destination
|
||||
metadata.Protocol = C.ProtocolDNS
|
||||
e.logger.InfoContext(ctx, "inbound DNS packet from ", source)
|
||||
e.router.HijackDNSPacket(ctx, payload, writer, metadata)
|
||||
}
|
||||
|
||||
func isEndpointLocalAddress(localAddresses []netip.Prefix, address netip.Addr) bool {
|
||||
for _, localPrefix := range localAddresses {
|
||||
if address == localPrefix.Addr() {
|
||||
|
||||
@@ -484,6 +484,10 @@ func (s *ServerEndpoint) JudgeFlow(network uint8, source netip.AddrPort, destina
|
||||
return judgeOpenVPNFlow(s.router, s.Tag(), s.Type(), s.localAddresses, network, source, destination, firstPacket)
|
||||
}
|
||||
|
||||
func (s *ServerEndpoint) NewDNSPacket(payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
s.newDNSPacket(log.ContextWithNewID(s.ctx), s, payload, source, destination, writer)
|
||||
}
|
||||
|
||||
func (s *ServerEndpoint) WritePackets(packets [][]byte) error {
|
||||
if !s.started.Load() {
|
||||
return E.New("OpenVPN server is not ready yet")
|
||||
|
||||
@@ -6,9 +6,13 @@ import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing-tun/gtcpip/header"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
tsTUN "github.com/sagernet/tailscale/net/tstun"
|
||||
"github.com/sagernet/tailscale/types/ipproto"
|
||||
"github.com/sagernet/tailscale/wgengine/filter"
|
||||
@@ -67,6 +71,19 @@ func (t *Endpoint) JudgeFlow(network uint8, source netip.AddrPort, destination n
|
||||
return adapter.JudgeFlow(t.router, t.Tag(), t.Type(), network, source, destination, firstPacket)
|
||||
}
|
||||
|
||||
func (t *Endpoint) NewDNSPacket(payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
ctx := log.ContextWithNewID(t.ctx)
|
||||
var metadata adapter.InboundContext
|
||||
metadata.Inbound = t.Tag()
|
||||
metadata.InboundType = t.Type()
|
||||
metadata.Network = N.NetworkUDP
|
||||
metadata.Source = source
|
||||
metadata.Destination = destination
|
||||
metadata.Protocol = C.ProtocolDNS
|
||||
t.logger.InfoContext(ctx, "inbound DNS packet from ", source)
|
||||
t.router.HijackDNSPacket(ctx, payload, writer, metadata)
|
||||
}
|
||||
|
||||
func (t *Endpoint) AttachReturn(returnPath tun.Return) error {
|
||||
t.returnAccess.Lock()
|
||||
defer t.returnAccess.Unlock()
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing-tun/gtcpip/header"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/json/badoption"
|
||||
@@ -516,11 +517,27 @@ func (t *Inbound) Close() error {
|
||||
|
||||
func (t *Inbound) JudgeFlow(network uint8, source netip.AddrPort, destination netip.AddrPort, firstPacket []byte) tun.FlowVerdict {
|
||||
if slices.Contains(t.dnsHijackAddress, destination.Addr()) {
|
||||
if network == uint8(header.UDPProtocolNumber) {
|
||||
return tun.FlowVerdict{Action: tun.ActionHijackDNS}
|
||||
}
|
||||
return tun.FlowVerdict{Action: tun.ActionAccept}
|
||||
}
|
||||
return adapter.JudgeFlow(t.router, t.tag, C.TypeTun, network, source, destination, firstPacket)
|
||||
}
|
||||
|
||||
func (t *Inbound) NewDNSPacket(payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
ctx := log.ContextWithNewID(t.ctx)
|
||||
var metadata adapter.InboundContext
|
||||
metadata.Inbound = t.tag
|
||||
metadata.InboundType = C.TypeTun
|
||||
metadata.Network = N.NetworkUDP
|
||||
metadata.Source = source
|
||||
metadata.Destination = destination
|
||||
metadata.Protocol = C.ProtocolDNS
|
||||
t.logger.InfoContext(ctx, "inbound DNS packet from ", source)
|
||||
t.router.HijackDNSPacket(ctx, payload, writer, metadata)
|
||||
}
|
||||
|
||||
func (t *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
|
||||
ctx = log.ContextWithNewID(ctx)
|
||||
var metadata adapter.InboundContext
|
||||
@@ -591,3 +608,7 @@ func (t *autoRedirectHandler) NewConnectionEx(ctx context.Context, conn net.Conn
|
||||
func (t *autoRedirectHandler) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
|
||||
panic("unexcepted")
|
||||
}
|
||||
|
||||
func (t *autoRedirectHandler) NewDNSPacket(payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
(*Inbound)(t).NewDNSPacket(payload, source, destination, writer)
|
||||
}
|
||||
|
||||
@@ -188,6 +188,19 @@ func (w *Endpoint) JudgeFlow(network uint8, source netip.AddrPort, destination n
|
||||
return adapter.JudgeFlow(w.router, w.Tag(), w.Type(), network, source, destination, firstPacket)
|
||||
}
|
||||
|
||||
func (w *Endpoint) NewDNSPacket(payload []byte, source M.Socksaddr, destination M.Socksaddr, writer N.PacketWriter) {
|
||||
ctx := log.ContextWithNewID(w.ctx)
|
||||
var metadata adapter.InboundContext
|
||||
metadata.Inbound = w.Tag()
|
||||
metadata.InboundType = w.Type()
|
||||
metadata.Network = N.NetworkUDP
|
||||
metadata.Source = source
|
||||
metadata.Destination = destination
|
||||
metadata.Protocol = C.ProtocolDNS
|
||||
w.logger.InfoContext(ctx, "inbound DNS packet from ", source)
|
||||
w.router.HijackDNSPacket(ctx, payload, writer, metadata)
|
||||
}
|
||||
|
||||
func (w *Endpoint) WritePackets(packets [][]byte) error {
|
||||
if !w.started.Load() {
|
||||
return E.New("WireGuard is not ready yet")
|
||||
|
||||
Reference in New Issue
Block a user