An attempt to use x/net in order to respond from the source IP address

This commit is contained in:
Frank Denis 2020-08-04 17:08:56 +02:00
parent 60d4c98f31
commit 32b1d8b273
1 changed files with 80 additions and 9 deletions

View File

@ -6,6 +6,7 @@ import (
"net" "net"
"os" "os"
"runtime" "runtime"
"strings"
"sync/atomic" "sync/atomic"
"time" "time"
@ -14,6 +15,8 @@ import (
stamps "github.com/jedisct1/go-dnsstamps" stamps "github.com/jedisct1/go-dnsstamps"
"github.com/miekg/dns" "github.com/miekg/dns"
"golang.org/x/crypto/curve25519" "golang.org/x/crypto/curve25519"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
) )
type Proxy struct { type Proxy struct {
@ -263,14 +266,82 @@ func (proxy *Proxy) StartProxy() {
} }
} }
func (proxy *Proxy) udpListener(clientPc *net.UDPConn) { type XConn struct {
defer clientPc.Close() conn interface{}
}
func (xConn *XConn) Write(p []byte) (n int, err error) {
return xConn.conn.(net.Conn).Write(p)
}
func (xConn *XConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
return xConn.conn.(net.PacketConn).WriteTo(p, addr)
}
type XNetUDPConn struct {
packetConnV4 *ipv4.PacketConn
packetConnV6 *ipv6.PacketConn
controlMessage *XControlMessage
}
type XControlMessage struct {
controlMessageV4 *ipv4.ControlMessage
controlMessageV6 *ipv6.ControlMessage
}
func (xNetConn *XNetUDPConn) fixSourceAddress(xControlMessage *XControlMessage) {
if xControlMessage == nil {
return
}
if xControlMessage.controlMessageV4 != nil {
xControlMessage.controlMessageV4.Src = xControlMessage.controlMessageV4.Dst
} else if xControlMessage.controlMessageV6 != nil {
xControlMessage.controlMessageV6.Src = xControlMessage.controlMessageV6.Dst
}
xNetConn.controlMessage = xControlMessage
}
func (xNetConn *XNetUDPConn) Close() error {
if xNetConn.packetConnV4 != nil {
return xNetConn.packetConnV4.Close()
}
return xNetConn.packetConnV6.Close()
}
func (xNetConn *XNetUDPConn) ReadFrom(b []byte) (n int, cm *XControlMessage, src net.Addr, err error) {
if xNetConn.packetConnV4 != nil {
xn, xcm, xsrc, xerr := xNetConn.packetConnV4.ReadFrom(b)
return xn, &XControlMessage{controlMessageV4: xcm}, xsrc, xerr
}
xn, xcm, xsrc, xerr := xNetConn.packetConnV6.ReadFrom(b)
return xn, &XControlMessage{controlMessageV6: xcm}, xsrc, xerr
}
func (xNetConn *XNetUDPConn) WriteTo(b []byte, cm *XControlMessage, dst net.Addr) (n int, err error) {
if xNetConn.packetConnV4 != nil {
return xNetConn.packetConnV4.WriteTo(b, cm.controlMessageV4, dst)
}
return xNetConn.packetConnV6.WriteTo(b, cm.controlMessageV6, dst)
}
func (proxy *Proxy) udpListener(clientPc net.PacketConn) {
isIPv6 := strings.HasPrefix(clientPc.LocalAddr().String(), "[")
var xClientPc XNetUDPConn
if !isIPv6 {
xClientPc = XNetUDPConn{packetConnV4: ipv4.NewPacketConn(clientPc)}
xClientPc.packetConnV4.SetControlMessage(ipv4.FlagDst, true)
} else {
xClientPc = XNetUDPConn{packetConnV6: ipv6.NewPacketConn(clientPc)}
xClientPc.packetConnV6.SetControlMessage(ipv6.FlagDst, true)
}
defer xClientPc.Close()
for { for {
buffer := make([]byte, MaxDNSPacketSize-1) buffer := make([]byte, MaxDNSPacketSize-1)
length, clientAddr, err := clientPc.ReadFrom(buffer) length, metadata, clientAddr, err := xClientPc.ReadFrom(buffer)
if err != nil { if err != nil {
return return
} }
xClientPc.fixSourceAddress(metadata)
packet := buffer[:length] packet := buffer[:length]
go func() { go func() {
start := time.Now() start := time.Now()
@ -279,17 +350,17 @@ func (proxy *Proxy) udpListener(clientPc *net.UDPConn) {
return return
} }
defer proxy.clientsCountDec() defer proxy.clientsCountDec()
proxy.processIncomingQuery("udp", proxy.mainProto, packet, &clientAddr, clientPc, start) proxy.processIncomingQuery("udp", proxy.mainProto, packet, &clientAddr, &XConn{conn: clientPc}, start)
}() }()
} }
} }
func (proxy *Proxy) udpListenerFromAddr(listenAddr *net.UDPAddr) error { func (proxy *Proxy) udpListenerFromAddr(listenAddr *net.UDPAddr) error {
clientPc, err := net.ListenUDP("udp", listenAddr) listener, err := net.ListenUDP("udp", listenAddr)
if err != nil { if err != nil {
return err return err
} }
proxy.registerUDPListener(clientPc) proxy.registerUDPListener(listener)
dlog.Noticef("Now listening to %v [UDP]", listenAddr) dlog.Noticef("Now listening to %v [UDP]", listenAddr)
return nil return nil
} }
@ -317,7 +388,7 @@ func (proxy *Proxy) tcpListener(acceptPc *net.TCPListener) {
return return
} }
clientAddr := clientPc.RemoteAddr() clientAddr := clientPc.RemoteAddr()
proxy.processIncomingQuery("tcp", "tcp", packet, &clientAddr, clientPc, start) proxy.processIncomingQuery("tcp", "tcp", packet, &clientAddr, &XConn{conn: clientPc}, start)
}() }()
} }
} }
@ -463,7 +534,7 @@ func (proxy *Proxy) clientsCountDec() {
} }
} }
func (proxy *Proxy) processIncomingQuery(clientProto string, serverProto string, query []byte, clientAddr *net.Addr, clientPc net.Conn, start time.Time) (response []byte) { func (proxy *Proxy) processIncomingQuery(clientProto string, serverProto string, query []byte, clientAddr *net.Addr, clientPc *XConn, start time.Time) (response []byte) {
if len(query) < MinDNSPacketSize { if len(query) < MinDNSPacketSize {
return return
} }
@ -628,7 +699,7 @@ func (proxy *Proxy) processIncomingQuery(clientProto string, serverProto string,
return return
} }
} }
clientPc.(net.PacketConn).WriteTo(response, *clientAddr) clientPc.WriteTo(response, *clientAddr)
if HasTCFlag(response) { if HasTCFlag(response) {
proxy.questionSizeEstimator.blindAdjust() proxy.questionSizeEstimator.blindAdjust()
} else { } else {