|
| 1 | +package remotedns |
| 2 | + |
| 3 | +import ( |
| 4 | + "net" |
| 5 | + |
| 6 | + "github.com/miekg/dns" |
| 7 | + "gvisor.dev/gvisor/pkg/tcpip" |
| 8 | + "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet" |
| 9 | + "gvisor.dev/gvisor/pkg/tcpip/stack" |
| 10 | + "gvisor.dev/gvisor/pkg/waiter" |
| 11 | + |
| 12 | + "github.com/xjasonlyu/tun2socks/v2/log" |
| 13 | + M "github.com/xjasonlyu/tun2socks/v2/metadata" |
| 14 | +) |
| 15 | + |
| 16 | +func RewriteMetadata(metadata *M.Metadata) bool { |
| 17 | + if !IsEnabled() { |
| 18 | + return false |
| 19 | + } |
| 20 | + dstName, found := getCachedName(metadata.DstIP) |
| 21 | + if !found { |
| 22 | + return false |
| 23 | + } |
| 24 | + metadata.DstIP = nil |
| 25 | + metadata.DstName = dstName |
| 26 | + return true |
| 27 | +} |
| 28 | + |
| 29 | +func HandleDNSQuery(s *stack.Stack, id stack.TransportEndpointID, ptr *stack.PacketBuffer) bool { |
| 30 | + if !IsEnabled() { |
| 31 | + return false |
| 32 | + } |
| 33 | + |
| 34 | + msg := dns.Msg{} |
| 35 | + err := msg.Unpack(ptr.Data().AsRange().ToSlice()) |
| 36 | + |
| 37 | + // Ignore UDP packets that are not IP queries to a recursive resolver |
| 38 | + if id.LocalPort != 53 || err != nil || len(msg.Question) != 1 || msg.Question[0].Qtype != dns.TypeA && |
| 39 | + msg.Question[0].Qtype != dns.TypeAAAA || msg.Question[0].Qclass != dns.ClassINET || !msg.RecursionDesired || |
| 40 | + msg.Response { |
| 41 | + return false |
| 42 | + } |
| 43 | + |
| 44 | + qname := msg.Question[0].Name |
| 45 | + qtype := msg.Question[0].Qtype |
| 46 | + |
| 47 | + log.Debugf("[DNS] query %s %s", dns.TypeToString[qtype], qname) |
| 48 | + |
| 49 | + var ip net.IP |
| 50 | + if qtype == dns.TypeA { |
| 51 | + rr := dns.A{} |
| 52 | + ip = findOrInsertNameAndReturnIP(4, qname) |
| 53 | + if ip == nil { |
| 54 | + log.Warnf("[DNS] IP space exhausted") |
| 55 | + return true |
| 56 | + } |
| 57 | + rr.A = ip |
| 58 | + rr.Hdr.Name = qname |
| 59 | + rr.Hdr.Ttl = dnsTTL |
| 60 | + rr.Hdr.Class = dns.ClassINET |
| 61 | + rr.Hdr.Rrtype = qtype |
| 62 | + msg.Answer = append(msg.Answer, &rr) |
| 63 | + } |
| 64 | + |
| 65 | + msg.Response = true |
| 66 | + msg.RecursionDesired = false |
| 67 | + msg.RecursionAvailable = true |
| 68 | + |
| 69 | + var wq waiter.Queue |
| 70 | + |
| 71 | + ep, err2 := s.NewEndpoint(ptr.TransportProtocolNumber, ptr.NetworkProtocolNumber, &wq) |
| 72 | + if err2 != nil { |
| 73 | + return true |
| 74 | + } |
| 75 | + defer ep.Close() |
| 76 | + |
| 77 | + ep.Bind(tcpip.FullAddress{NIC: ptr.NICID, Addr: id.LocalAddress, Port: id.LocalPort}) |
| 78 | + conn := gonet.NewUDPConn(&wq, ep) |
| 79 | + defer conn.Close() |
| 80 | + packed, err := msg.Pack() |
| 81 | + if err != nil { |
| 82 | + return true |
| 83 | + } |
| 84 | + _, _ = conn.WriteTo(packed, &net.UDPAddr{IP: id.RemoteAddress.AsSlice(), Port: int(id.RemotePort)}) |
| 85 | + return true |
| 86 | +} |
0 commit comments