fix: system stack's dns hijack not working

This commit is contained in:
wwqgtxx 2023-12-08 01:25:07 +08:00
parent cbec564af9
commit 9ac4738ef9

View file

@ -73,7 +73,7 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta
ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout) ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout)
defer cancel() defer cancel()
inData := buff[:n] inData := buff[:n]
msg, err := RelayDnsPacket(ctx, inData) msg, err := RelayDnsPacket(ctx, inData, buff)
if err != nil { if err != nil {
return err return err
} }
@ -110,6 +110,8 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
conn2 = nil conn2 = nil
}() }()
rwOptions := network.ReadWaitOptions{ rwOptions := network.ReadWaitOptions{
FrontHeadroom: network.CalculateFrontHeadroom(conn),
RearHeadroom: network.CalculateRearHeadroom(conn),
MTU: 2 * 1024, // safe size which is 1232 from https://dnsflagday.net/2020/, so 2048 is enough MTU: 2 * 1024, // safe size which is 1232 from https://dnsflagday.net/2020/, so 2048 is enough
} }
readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn)
@ -118,24 +120,24 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
} }
for { for {
var ( var (
buff *buf.Buffer readBuff *buf.Buffer
dest M.Socksaddr dest M.Socksaddr
err error err error
) )
_ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout)) _ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout))
buff = nil // clear last loop status, avoid repeat release readBuff = nil // clear last loop status, avoid repeat release
if isReadWaiter { if isReadWaiter {
buff, dest, err = readWaiter.WaitReadPacket() readBuff, dest, err = readWaiter.WaitReadPacket()
} else { } else {
buff = rwOptions.NewPacketBuffer() readBuff = rwOptions.NewPacketBuffer()
dest, err = conn.ReadPacket(buff) dest, err = conn.ReadPacket(readBuff)
if buff != nil { if readBuff != nil {
rwOptions.PostReturn(buff) rwOptions.PostReturn(readBuff)
} }
} }
if err != nil { if err != nil {
if buff != nil { if readBuff != nil {
buff.Release() readBuff.Release()
} }
if sing.ShouldIgnorePacketError(err) { if sing.ShouldIgnorePacketError(err) {
break break
@ -145,26 +147,30 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
go func() { go func() {
ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout) ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout)
defer cancel() defer cancel()
inData := buff.Bytes() inData := readBuff.Bytes()
msg, err := RelayDnsPacket(ctx, inData) writeBuff := readBuff
if writeBuff.Cap() < rwOptions.MTU { // only create a new buffer when space don't enough
writeBuff = rwOptions.NewPacketBuffer()
}
msg, err := RelayDnsPacket(ctx, inData, writeBuff.FreeBytes())
if writeBuff != readBuff {
readBuff.Release()
}
if err != nil { if err != nil {
buff.Release() writeBuff.Release()
return
}
buff.Reset()
_, err = buff.Write(msg)
if err != nil {
buff.Release()
return return
} }
writeBuff.Truncate(len(msg))
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()
conn := conn2 conn := conn2
if conn == nil { if conn == nil {
writeBuff.Release()
return return
} }
err = conn.WritePacket(buff, dest) // WritePacket will release buff err = conn.WritePacket(writeBuff, dest) // WritePacket will release writeBuff
if err != nil { if err != nil {
writeBuff.Release()
return return
} }
}() }()
@ -174,7 +180,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
return h.ListenerHandler.NewPacketConnection(ctx, conn, metadata) return h.ListenerHandler.NewPacketConnection(ctx, conn, metadata)
} }
func RelayDnsPacket(ctx context.Context, payload []byte) ([]byte, error) { func RelayDnsPacket(ctx context.Context, payload []byte, target []byte) ([]byte, error) {
msg := &D.Msg{} msg := &D.Msg{}
if err := msg.Unpack(payload); err != nil { if err := msg.Unpack(payload); err != nil {
return nil, err return nil, err
@ -184,10 +190,10 @@ func RelayDnsPacket(ctx context.Context, payload []byte) ([]byte, error) {
if err != nil { if err != nil {
m := new(D.Msg) m := new(D.Msg)
m.SetRcode(msg, D.RcodeServerFailure) m.SetRcode(msg, D.RcodeServerFailure)
return m.Pack() return m.PackBuffer(target)
} }
r.SetRcode(msg, r.Rcode) r.SetRcode(msg, r.Rcode)
r.Compress = true r.Compress = true
return r.Pack() return r.PackBuffer(target)
} }