2023-01-23 18:54:21 +07:00
/ *
* SPDX - License - Identifier : AGPL - 3.0 - only
2023-02-18 17:27:28 +07:00
* Copyright ( c ) 2022 - 2023 , v2rayA Organization < team @ v2raya . org >
2023-01-23 18:54:21 +07:00
* /
package control
import (
"encoding/binary"
2023-02-21 15:10:44 +07:00
"encoding/gob"
2023-02-04 19:53:29 +07:00
"errors"
2023-01-23 18:54:21 +07:00
"fmt"
2023-02-21 15:10:44 +07:00
"github.com/mzz2017/softwind/pkg/zeroalloc/buffer"
2023-01-29 12:38:15 +07:00
"github.com/mzz2017/softwind/pool"
2023-01-31 18:54:11 +07:00
"github.com/sirupsen/logrus"
2023-02-13 17:26:31 +07:00
"github.com/v2rayA/dae/common"
2023-01-23 19:01:24 +07:00
"github.com/v2rayA/dae/common/consts"
2023-02-04 14:28:48 +07:00
"github.com/v2rayA/dae/component/outbound/dialer"
2023-02-15 00:53:53 +07:00
"github.com/v2rayA/dae/component/sniffing"
2023-01-23 18:54:21 +07:00
"golang.org/x/net/dns/dnsmessage"
2023-02-09 10:40:34 +07:00
"io"
2023-01-23 18:54:21 +07:00
"net"
"net/netip"
2023-02-04 16:11:01 +07:00
"strings"
2023-02-06 12:56:43 +07:00
"syscall"
2023-01-23 18:54:21 +07:00
"time"
2023-02-21 15:10:44 +07:00
"unsafe"
2023-01-23 18:54:21 +07:00
)
const (
DefaultNatTimeout = 3 * time . Minute
DnsNatTimeout = 17 * time . Second // RFC 5452
2023-02-13 09:52:40 +07:00
MaxRetry = 2
2023-01-23 18:54:21 +07:00
)
2023-02-12 20:50:15 +07:00
var (
UnspecifiedAddr4 = netip . AddrFrom4 ( [ 4 ] byte { } )
UnspecifiedAddr6 = netip . AddrFrom16 ( [ 16 ] byte { } )
)
2023-02-19 21:16:59 +07:00
func ChooseNatTimeout ( data [ ] byte , sniffDns bool ) ( dmsg * dnsmessage . Message , timeout time . Duration ) {
2023-01-23 18:54:21 +07:00
var dnsmsg dnsmessage . Message
if err := dnsmsg . Unpack ( data ) ; err == nil {
//log.Printf("DEBUG: lookup %v", dnsmsg.Questions[0].Name)
return & dnsmsg , DnsNatTimeout
}
return nil , DefaultNatTimeout
}
2023-02-21 15:10:44 +07:00
func ParseAddrHdr ( data [ ] byte ) ( hdr * bpfDstRoutingResult , dataOffset int , err error ) {
dataOffset = int ( unsafe . Sizeof ( bpfDstRoutingResult { } ) )
2023-01-23 18:54:21 +07:00
if len ( data ) < dataOffset {
return nil , 0 , fmt . Errorf ( "data is too short to parse AddrHdr" )
}
2023-02-21 15:10:44 +07:00
_hdr := * ( * bpfDstRoutingResult ) ( unsafe . Pointer ( & data [ 0 ] ) )
_hdr . Port = common . Ntohs ( _hdr . Port )
return & _hdr , dataOffset , nil
2023-01-23 18:54:21 +07:00
}
2023-02-20 17:06:54 +07:00
func sendPktWithHdrWithFlag ( data [ ] byte , mark uint32 , from netip . AddrPort , lConn * net . UDPConn , to netip . AddrPort , lanWanFlag consts . LanWanFlag ) error {
2023-02-21 15:10:44 +07:00
hdr := bpfDstRoutingResult {
Ip : common . Ipv6ByteSliceToUint32Array ( from . Addr ( ) . AsSlice ( ) ) ,
Port : common . Htons ( from . Port ( ) ) ,
RoutingResult : bpfRoutingResult {
Outbound : uint8 ( lanWanFlag ) , // Pass some message to the kernel program.
} ,
2023-01-23 18:54:21 +07:00
}
2023-02-21 15:10:44 +07:00
buf := pool . Get ( int ( unsafe . Sizeof ( hdr ) ) + len ( data ) )
2023-01-23 18:54:21 +07:00
defer pool . Put ( buf )
2023-02-21 15:10:44 +07:00
b := buffer . NewBufferFrom ( buf )
defer b . Put ( )
if err := gob . NewEncoder ( b ) . Encode ( & hdr ) ; err != nil {
return err
}
copy ( buf [ int ( unsafe . Sizeof ( hdr ) ) : ] , data )
2023-01-23 18:54:21 +07:00
//log.Println("from", from, "to", to)
_ , err := lConn . WriteToUDPAddrPort ( buf , to )
return err
}
2023-02-12 20:50:15 +07:00
// sendPkt uses bind first, and fallback to send hdr if addr is in use.
2023-02-13 11:54:04 +07:00
func sendPkt ( data [ ] byte , from netip . AddrPort , realTo , to netip . AddrPort , lConn * net . UDPConn , lanWanFlag consts . LanWanFlag ) ( err error ) {
2023-02-06 12:56:43 +07:00
d := net . Dialer { Control : func ( network , address string , c syscall . RawConn ) error {
return dialer . BindControl ( c , from )
} }
2023-02-12 20:50:15 +07:00
var conn net . Conn
conn , err = d . Dial ( "udp" , realTo . String ( ) )
2023-02-06 12:56:43 +07:00
if err != nil {
2023-02-12 20:50:15 +07:00
if errors . Is ( err , syscall . EADDRINUSE ) {
// Port collision, use traditional method.
2023-02-20 17:06:54 +07:00
return sendPktWithHdrWithFlag ( data , 0 , from , lConn , to , lanWanFlag )
2023-02-12 20:50:15 +07:00
}
2023-02-06 12:56:43 +07:00
return err
}
2023-02-12 20:50:15 +07:00
defer conn . Close ( )
2023-02-06 12:56:43 +07:00
uConn := conn . ( * net . UDPConn )
_ , err = uConn . Write ( data )
return err
}
2023-02-13 11:54:04 +07:00
func ( c * ControlPlane ) WriteToUDP ( lanWanFlag consts . LanWanFlag , lConn * net . UDPConn , realTo , to netip . AddrPort , isDNS bool , dummyFrom * netip . AddrPort , validateRushAnsFunc func ( from netip . AddrPort ) bool ) UdpHandler {
2023-01-23 18:54:21 +07:00
return func ( data [ ] byte , from netip . AddrPort ) ( err error ) {
2023-02-05 12:05:28 +07:00
// Do not return conn-unrelated err in this func.
2023-01-23 18:54:21 +07:00
if isDNS {
2023-02-09 10:40:34 +07:00
validateRushAns := validateRushAnsFunc ( from )
2023-02-05 12:05:28 +07:00
data , err = c . DnsRespHandler ( data , validateRushAns )
2023-01-23 18:54:21 +07:00
if err != nil {
2023-02-06 15:22:07 +07:00
if validateRushAns && errors . Is ( err , SuspectedRushAnswerError ) {
2023-02-04 19:53:29 +07:00
// Reject DNS rush-answer.
2023-02-05 20:05:23 +07:00
c . log . WithFields ( logrus . Fields {
"from" : from ,
} ) . Tracef ( "DNS rush-answer rejected" )
2023-02-04 19:53:29 +07:00
return err
}
2023-02-19 21:16:59 +07:00
if c . log . IsLevelEnabled ( logrus . DebugLevel ) {
c . log . Debugf ( "DnsRespHandler: %v" , err )
}
2023-02-05 12:05:28 +07:00
if data == nil {
return nil
}
2023-01-23 18:54:21 +07:00
}
}
2023-01-24 16:15:27 +07:00
if dummyFrom != nil {
from = * dummyFrom
}
2023-02-12 20:50:15 +07:00
return sendPkt ( data , from , realTo , to , lConn , lanWanFlag )
2023-01-23 18:54:21 +07:00
}
}
2023-02-20 17:06:54 +07:00
func ( c * ControlPlane ) handlePkt ( lConn * net . UDPConn , data [ ] byte , src , pktDst , realDst netip . AddrPort , routingResult * bpfRoutingResult ) ( err error ) {
2023-02-13 11:54:04 +07:00
var lanWanFlag consts . LanWanFlag
2023-02-12 20:50:15 +07:00
var realSrc netip . AddrPort
2023-02-15 00:53:53 +07:00
var domain string
2023-02-12 20:50:15 +07:00
useAssign := pktDst == realDst // Use sk_assign instead of modify target ip/port.
if useAssign {
2023-02-13 11:54:04 +07:00
lanWanFlag = consts . LanWanFlag_IsLan
2023-02-12 20:50:15 +07:00
realSrc = src
} else {
2023-02-13 11:54:04 +07:00
lanWanFlag = consts . LanWanFlag_IsWan
2023-02-12 20:50:15 +07:00
// From localhost, so dst IP is src IP.
realSrc = netip . AddrPortFrom ( pktDst . Addr ( ) , src . Port ( ) )
}
2023-02-12 22:11:40 +07:00
mustDirect := false
2023-02-20 17:06:54 +07:00
outboundIndex := consts . OutboundIndex ( routingResult . Outbound )
2023-02-06 12:56:43 +07:00
switch outboundIndex {
2023-01-23 18:54:21 +07:00
case consts . OutboundDirect :
2023-02-12 22:11:40 +07:00
case consts . OutboundMustDirect :
mustDirect = true
fallthrough
2023-01-24 15:27:19 +07:00
case consts . OutboundControlPlaneDirect :
2023-02-19 21:16:59 +07:00
if c . log . IsLevelEnabled ( logrus . TraceLevel ) {
c . log . Tracef ( "outbound: %v => %v" ,
outboundIndex . String ( ) ,
consts . OutboundDirect . String ( ) ,
)
}
2023-02-12 22:11:40 +07:00
outboundIndex = consts . OutboundDirect
2023-01-23 18:54:21 +07:00
default :
}
2023-02-06 12:56:43 +07:00
if int ( outboundIndex ) >= len ( c . outbounds ) {
2023-02-11 20:34:49 +07:00
return fmt . Errorf ( "outbound %v out of range [0, %v]" , outboundIndex , len ( c . outbounds ) - 1 )
2023-01-30 14:50:55 +07:00
}
2023-02-06 12:56:43 +07:00
outbound := c . outbounds [ outboundIndex ]
2023-02-19 21:16:59 +07:00
// To keep consistency with kernel program, we only sniff DNS request sent to 53.
dnsMessage , natTimeout := ChooseNatTimeout ( data , realDst . Port ( ) == 53 )
2023-01-23 18:54:21 +07:00
// We should cache DNS records and set record TTL to 0, in order to monitor the dns req and resp in real time.
isDns := dnsMessage != nil
2023-01-24 16:15:27 +07:00
var dummyFrom * netip . AddrPort
2023-02-12 20:50:15 +07:00
destToSend := realDst
2023-01-23 18:54:21 +07:00
if isDns {
2023-02-17 23:49:35 +07:00
if resp := c . LookupDnsRespCache_ ( dnsMessage ) ; resp != nil {
2023-02-04 19:53:29 +07:00
// Send cache to client directly.
2023-02-12 20:50:15 +07:00
if err = sendPkt ( resp , destToSend , realSrc , src , lConn , lanWanFlag ) ; err != nil {
2023-01-23 18:54:21 +07:00
return fmt . Errorf ( "failed to write cached DNS resp: %w" , err )
}
2023-01-31 18:54:11 +07:00
if c . log . IsLevelEnabled ( logrus . DebugLevel ) && len ( dnsMessage . Questions ) > 0 {
q := dnsMessage . Questions [ 0 ]
2023-02-04 14:28:48 +07:00
c . log . Tracef ( "UDP(DNS) %v <-[%v]-> Cache: %v %v" ,
2023-02-13 11:54:04 +07:00
RefineSourceToShow ( realSrc , realDst . Addr ( ) , lanWanFlag ) , outbound . Name , strings . ToLower ( q . Name . String ( ) ) , q . Type ,
2023-01-31 18:54:11 +07:00
)
}
2023-01-23 18:54:21 +07:00
return nil
2023-02-04 19:53:29 +07:00
}
2023-02-04 16:11:01 +07:00
2023-02-04 19:53:29 +07:00
// Flip dns question to reduce dns pollution.
FlipDnsQuestionCase ( dnsMessage )
// Make sure there is additional record OPT in the request to filter DNS rush-answer in the response process.
// Because rush-answer has no resp OPT. We can distinguish them from multiple responses.
// Note that additional record OPT may not be supported by home router either.
_ , _ = EnsureAdditionalOpt ( dnsMessage , true )
// Re-pack DNS packet.
if data , err = dnsMessage . Pack ( ) ; err != nil {
return fmt . Errorf ( "pack flipped dns packet: %w" , err )
2023-02-04 14:28:48 +07:00
}
2023-02-15 00:53:53 +07:00
} else {
// Sniff Quic
sniffer := sniffing . NewPacketSniffer ( data )
domain , err = sniffer . SniffQuic ( )
if err != nil && ! sniffing . IsSniffingError ( err ) {
sniffer . Close ( )
return err
}
sniffer . Close ( )
2023-02-04 14:28:48 +07:00
}
2023-01-31 18:54:11 +07:00
2023-02-08 20:28:08 +07:00
l4proto := consts . L4ProtoStr_UDP
2023-02-12 20:50:15 +07:00
ipversion := consts . IpVersionFromAddr ( realDst . Addr ( ) )
2023-02-09 10:40:34 +07:00
var dialerForNew * dialer . Dialer
2023-02-12 20:50:15 +07:00
// For DNS request, modify realDst to dns upstream.
2023-02-09 10:40:34 +07:00
// NOTICE: We might modify l4proto and ipversion.
2023-02-10 10:04:16 +07:00
dnsUpstream , err := c . dnsUpstream . GetUpstream ( )
2023-02-09 18:22:37 +07:00
if err != nil {
return err
}
2023-02-12 22:11:40 +07:00
if isDns && dnsUpstream != nil && ! mustDirect {
2023-02-09 10:40:34 +07:00
// Modify dns target to upstream.
// NOTICE: Routing was calculated in advance by the eBPF program.
2023-02-12 22:11:40 +07:00
/// Choose the best l4proto+ipversion dialer, and change taregt DNS to the best ipversion DNS upstream for DNS request.
2023-02-09 10:40:34 +07:00
// Get available ipversions and l4protos for DNS upstream.
2023-02-09 18:22:37 +07:00
ipversions , l4protos := dnsUpstream . SupportedNetworks ( )
2023-02-09 10:40:34 +07:00
var (
bestDialer * dialer . Dialer
bestLatency time . Duration
bestTarget netip . AddrPort
)
2023-02-19 21:16:59 +07:00
if c . log . IsLevelEnabled ( logrus . TraceLevel ) {
c . log . WithFields ( logrus . Fields {
"ipversions" : ipversions ,
"l4protos" : l4protos ,
"src" : realSrc . String ( ) ,
} ) . Traceln ( "Choose DNS path" )
}
2023-02-09 10:40:34 +07:00
// Get the min latency path.
2023-02-12 14:39:00 +07:00
networkType := dialer . NetworkType {
IsDns : isDns ,
}
2023-02-09 10:40:34 +07:00
for _ , ver := range ipversions {
for _ , proto := range l4protos {
2023-02-12 14:39:00 +07:00
networkType . L4Proto = proto
networkType . IpVersion = ver
d , latency , err := outbound . Select ( & networkType )
2023-02-09 10:40:34 +07:00
if err != nil {
continue
}
2023-02-19 21:16:59 +07:00
if c . log . IsLevelEnabled ( logrus . TraceLevel ) {
c . log . WithFields ( logrus . Fields {
"name" : d . Name ( ) ,
"latency" : latency ,
"network" : networkType . String ( ) ,
"outbound" : outbound . Name ,
} ) . Traceln ( "Choice" )
}
2023-02-09 10:40:34 +07:00
if bestDialer == nil || latency < bestLatency {
bestDialer = d
bestLatency = latency
l4proto = proto
ipversion = ver
}
2023-01-31 18:54:11 +07:00
}
2023-02-09 10:40:34 +07:00
}
switch ipversion {
case consts . IpVersionStr_4 :
2023-02-09 18:22:37 +07:00
bestTarget = netip . AddrPortFrom ( dnsUpstream . Ip4 , dnsUpstream . Port )
2023-02-09 10:40:34 +07:00
case consts . IpVersionStr_6 :
2023-02-09 18:22:37 +07:00
bestTarget = netip . AddrPortFrom ( dnsUpstream . Ip6 , dnsUpstream . Port )
2023-02-09 10:40:34 +07:00
}
dialerForNew = bestDialer
2023-02-12 20:50:15 +07:00
dummyFrom = & realDst
2023-02-09 10:40:34 +07:00
destToSend = bestTarget
2023-02-19 21:16:59 +07:00
if c . log . IsLevelEnabled ( logrus . TraceLevel ) {
c . log . WithFields ( logrus . Fields {
"Original" : RefineAddrPortToShow ( realDst ) ,
"New" : destToSend ,
"Network" : string ( l4proto ) + string ( ipversion ) ,
} ) . Traceln ( "Modify DNS target" )
}
2023-02-09 10:40:34 +07:00
}
2023-02-12 14:39:00 +07:00
networkType := & dialer . NetworkType {
L4Proto : l4proto ,
IpVersion : ipversion ,
IsDns : true ,
}
2023-02-09 10:40:34 +07:00
if dialerForNew == nil {
2023-02-12 14:39:00 +07:00
dialerForNew , _ , err = outbound . Select ( networkType )
2023-02-09 10:40:34 +07:00
if err != nil {
2023-02-15 00:53:53 +07:00
return fmt . Errorf ( "failed to select dialer from group %v (%v, dns?:%v,from: %v): %w" , outbound . Name , networkType . StringWithoutDns ( ) , isDns , realSrc . String ( ) , err )
2023-02-09 10:40:34 +07:00
}
2023-02-08 20:28:08 +07:00
}
2023-02-04 14:28:48 +07:00
2023-02-09 10:40:34 +07:00
var isNew bool
var realDialer * dialer . Dialer
2023-02-12 20:50:15 +07:00
udpHandler := c . WriteToUDP ( lanWanFlag , lConn , realSrc , src , isDns , dummyFrom , func ( from netip . AddrPort ) bool {
2023-02-09 10:40:34 +07:00
// We only validate rush-ans when outbound is direct and pkt does not send to a home device.
// Because additional record OPT may not be supported by home router.
// So se should trust home devices even if they make rush-answer (or looks like).
2023-02-13 17:26:31 +07:00
return outboundIndex == consts . OutboundDirect && ! common . ConvergeIp ( from . Addr ( ) ) . IsPrivate ( )
2023-02-09 10:40:34 +07:00
} )
// Dial and send.
2023-02-17 23:49:35 +07:00
// TODO: Rewritten domain should not use full-cone (such as VMess Packet Addr).
// Maybe we should set up a mapping for UDP: Dialer + Target Domain => Remote Resolved IP.
destToSend = netip . AddrPortFrom ( common . ConvergeIp ( destToSend . Addr ( ) ) , destToSend . Port ( ) )
tgtToSend := c . ChooseDialTarget ( outboundIndex , destToSend , domain )
2023-02-09 10:40:34 +07:00
switch l4proto {
case consts . L4ProtoStr_UDP :
// Get udp endpoint.
var ue * UdpEndpoint
2023-02-13 09:52:40 +07:00
retry := 0
2023-02-09 10:40:34 +07:00
getNew :
2023-02-13 09:52:40 +07:00
if retry > MaxRetry {
return fmt . Errorf ( "touch max retry limit" )
}
2023-02-20 17:06:54 +07:00
2023-02-13 11:54:04 +07:00
ue , isNew , err = DefaultUdpEndpointPool . GetOrCreate ( realSrc , & UdpEndpointOptions {
2023-02-09 10:40:34 +07:00
Handler : udpHandler ,
NatTimeout : natTimeout ,
2023-02-20 17:06:54 +07:00
Dialer : dialerForNew ,
Network : GetNetwork ( "udp" , routingResult . Mark ) ,
Target : tgtToSend ,
2023-02-09 10:40:34 +07:00
} )
if err != nil {
2023-02-13 14:27:36 +07:00
return fmt . Errorf ( "failed to GetOrCreate (policy: %v): %w" , outbound . GetSelectionPolicy ( ) , err )
2023-02-09 10:40:34 +07:00
}
2023-02-17 23:49:35 +07:00
2023-02-09 10:40:34 +07:00
// If the udp endpoint has been not alive, remove it from pool and get a new one.
2023-02-17 23:49:35 +07:00
if ! isNew && outbound . GetSelectionPolicy ( ) != consts . DialerSelectionPolicy_Fixed && ! ue . Dialer . MustGetAlive ( networkType ) {
2023-02-19 21:16:59 +07:00
if c . log . IsLevelEnabled ( logrus . DebugLevel ) {
c . log . WithFields ( logrus . Fields {
"src" : RefineSourceToShow ( realSrc , realDst . Addr ( ) , lanWanFlag ) ,
"network" : networkType . String ( ) ,
"dialer" : ue . Dialer . Name ( ) ,
"retry" : retry ,
} ) . Debugln ( "Old udp endpoint was not alive and removed." )
}
2023-02-13 11:54:04 +07:00
_ = DefaultUdpEndpointPool . Remove ( realSrc , ue )
2023-02-13 09:52:40 +07:00
retry ++
2023-02-09 10:40:34 +07:00
goto getNew
}
// This is real dialer.
realDialer = ue . Dialer
2023-02-17 23:49:35 +07:00
_ , err = ue . WriteTo ( data , tgtToSend )
2023-02-09 10:40:34 +07:00
if err != nil {
2023-02-19 21:16:59 +07:00
if c . log . IsLevelEnabled ( logrus . DebugLevel ) {
c . log . WithFields ( logrus . Fields {
"to" : destToSend . String ( ) ,
"domain" : domain ,
2023-02-21 15:10:44 +07:00
"pid" : routingResult . Pid ,
"pname" : ProcessName2String ( routingResult . Pname [ : ] ) ,
"mac" : Mac2String ( routingResult . Mac [ : ] ) ,
2023-02-19 21:16:59 +07:00
"from" : realSrc . String ( ) ,
"network" : networkType . String ( ) ,
"err" : err . Error ( ) ,
"retry" : retry ,
} ) . Debugln ( "Failed to write UDP packet request. Try to remove old UDP endpoint and retry." )
}
2023-02-13 11:54:04 +07:00
_ = DefaultUdpEndpointPool . Remove ( realSrc , ue )
2023-02-13 09:52:40 +07:00
retry ++
goto getNew
2023-02-09 10:40:34 +07:00
}
case consts . L4ProtoStr_TCP :
// MUST be DNS.
if ! isDns {
return fmt . Errorf ( "UDP to TCP only support DNS request" )
}
2023-02-15 00:53:53 +07:00
isNew = true
2023-02-09 10:40:34 +07:00
realDialer = dialerForNew
// We can block because we are in a coroutine.
2023-02-20 17:06:54 +07:00
conn , err := dialerForNew . Dial ( GetNetwork ( "tcp" , routingResult . Mark ) , tgtToSend )
2023-02-09 10:40:34 +07:00
if err != nil {
return fmt . Errorf ( "failed to dial proxy to tcp: %w" , err )
}
defer conn . Close ( )
_ = conn . SetDeadline ( time . Now ( ) . Add ( natTimeout ) )
// We should write two byte length in the front of TCP DNS request.
2023-02-12 14:39:00 +07:00
bReq := pool . Get ( 2 + len ( data ) )
defer pool . Put ( bReq )
binary . BigEndian . PutUint16 ( bReq , uint16 ( len ( data ) ) )
copy ( bReq [ 2 : ] , data )
_ , err = conn . Write ( bReq )
2023-02-09 10:40:34 +07:00
if err != nil {
2023-02-12 14:39:00 +07:00
return fmt . Errorf ( "failed to write DNS req: %w" , err )
2023-02-09 10:40:34 +07:00
}
// Read two byte length.
2023-02-12 14:39:00 +07:00
if _ , err = io . ReadFull ( conn , bReq [ : 2 ] ) ; err != nil {
2023-02-09 10:40:34 +07:00
return fmt . Errorf ( "failed to read DNS resp payload length: %w" , err )
}
2023-02-12 14:39:00 +07:00
respLen := int ( binary . BigEndian . Uint16 ( bReq ) )
// Try to reuse the buf.
var buf [ ] byte
if len ( bReq ) < respLen {
buf = pool . Get ( respLen )
defer pool . Put ( buf )
} else {
buf = bReq
}
var n int
2023-02-17 23:49:35 +07:00
if n , err = io . ReadFull ( conn , buf [ : respLen ] ) ; err != nil {
2023-02-09 10:40:34 +07:00
return fmt . Errorf ( "failed to read DNS resp payload: %w" , err )
}
2023-02-12 14:39:00 +07:00
if err = udpHandler ( buf [ : n ] , destToSend ) ; err != nil {
2023-02-09 10:40:34 +07:00
return fmt . Errorf ( "failed to write DNS resp to client: %w" , err )
}
}
// Print log.
if isNew || isDns {
2023-02-08 20:32:20 +07:00
// Only print routing for new connection to avoid the log exploded (Quic and BT).
if isDns && c . log . IsLevelEnabled ( logrus . DebugLevel ) && len ( dnsMessage . Questions ) > 0 {
q := dnsMessage . Questions [ 0 ]
c . log . WithFields ( logrus . Fields {
2023-02-08 21:43:28 +07:00
"network" : string ( l4proto ) + string ( ipversion ) + "(DNS)" ,
2023-02-08 20:32:20 +07:00
"outbound" : outbound . Name ,
2023-02-13 14:27:36 +07:00
"policy" : outbound . GetSelectionPolicy ( ) ,
2023-02-09 10:40:34 +07:00
"dialer" : realDialer . Name ( ) ,
2023-02-08 20:32:20 +07:00
"qname" : strings . ToLower ( q . Name . String ( ) ) ,
"qtype" : q . Type ,
2023-02-21 15:10:44 +07:00
"pid" : routingResult . Pid ,
"pname" : ProcessName2String ( routingResult . Pname [ : ] ) ,
"mac" : Mac2String ( routingResult . Mac [ : ] ) ,
2023-02-08 20:32:20 +07:00
} ) . Infof ( "%v <-> %v" ,
2023-02-13 11:54:04 +07:00
RefineSourceToShow ( realSrc , realDst . Addr ( ) , lanWanFlag ) , RefineAddrPortToShow ( destToSend ) ,
2023-02-08 20:32:20 +07:00
)
2023-02-19 21:16:59 +07:00
} else if c . log . IsLevelEnabled ( logrus . InfoLevel ) {
2023-02-21 15:10:44 +07:00
if isDns && len ( dnsMessage . Questions ) > 0 {
domain = strings . ToLower ( dnsMessage . Questions [ 0 ] . Name . String ( ) )
}
2023-02-08 20:32:20 +07:00
c . log . WithFields ( logrus . Fields {
2023-02-08 21:43:28 +07:00
"network" : string ( l4proto ) + string ( ipversion ) ,
2023-02-08 20:32:20 +07:00
"outbound" : outbound . Name ,
2023-02-13 14:27:36 +07:00
"policy" : outbound . GetSelectionPolicy ( ) ,
2023-02-09 10:40:34 +07:00
"dialer" : realDialer . Name ( ) ,
2023-02-15 00:53:53 +07:00
"domain" : domain ,
2023-02-21 15:10:44 +07:00
"pid" : routingResult . Pid ,
"pname" : ProcessName2String ( routingResult . Pname [ : ] ) ,
"mac" : Mac2String ( routingResult . Mac [ : ] ) ,
2023-02-08 20:32:20 +07:00
} ) . Infof ( "%v <-> %v" ,
2023-02-13 11:54:04 +07:00
RefineSourceToShow ( realSrc , realDst . Addr ( ) , lanWanFlag ) , RefineAddrPortToShow ( destToSend ) ,
2023-02-08 20:32:20 +07:00
)
}
2023-01-23 18:54:21 +07:00
}
2023-02-09 10:40:34 +07:00
2023-01-23 18:54:21 +07:00
return nil
}