github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/components/resolver/hosts.go (about) 1 package resolver 2 3 import ( 4 "context" 5 "net" 6 "strings" 7 8 "github.com/Asutorufa/yuhaiin/pkg/net/netapi" 9 "github.com/Asutorufa/yuhaiin/pkg/protos/config" 10 "github.com/Asutorufa/yuhaiin/pkg/utils/yerror" 11 "golang.org/x/net/dns/dnsmessage" 12 ) 13 14 type Hosts struct { 15 hosts map[string]*hostsEntry 16 dialer netapi.Proxy 17 resolver netapi.Resolver 18 } 19 20 type hostsEntry struct { 21 V netapi.Address 22 portMap map[uint16]netapi.Address 23 } 24 25 func NewHosts(dialer netapi.Proxy, resolver netapi.Resolver) *Hosts { 26 return &Hosts{dialer: dialer, resolver: resolver, hosts: map[string]*hostsEntry{}} 27 } 28 29 func (h *Hosts) Update(c *config.Setting) { 30 store := map[string]*hostsEntry{} 31 32 for k, v := range c.Dns.Hosts { 33 _, _, e1 := net.SplitHostPort(k) 34 _, _, e2 := net.SplitHostPort(v) 35 36 if e1 == nil && e2 == nil { 37 kaddr, err1 := netapi.ParseAddress(0, k) 38 addr, err2 := netapi.ParseAddress(0, v) 39 if err1 == nil && err2 == nil && kaddr.Port().Port() != 0 && addr.Port().Port() != 0 { 40 v, ok := store[kaddr.Hostname()] 41 if !ok { 42 v = &hostsEntry{} 43 store[kaddr.Hostname()] = v 44 } 45 46 if v.portMap == nil { 47 v.portMap = map[uint16]netapi.Address{} 48 } 49 50 v.portMap[kaddr.Port().Port()] = addr 51 } 52 } 53 54 if e1 != nil && e2 != nil { 55 he, ok := store[k] 56 if !ok { 57 he = &hostsEntry{} 58 store[k] = he 59 } 60 61 he.V = netapi.ParseAddressPort(0, v, netapi.EmptyPort) 62 } 63 } 64 65 h.hosts = store 66 } 67 68 func (h *Hosts) Dispatch(ctx context.Context, addr netapi.Address) (netapi.Address, error) { 69 haddr := h.dispatchAddr(ctx, addr) 70 return h.dialer.Dispatch(ctx, haddr) 71 } 72 73 func (h *Hosts) Conn(ctx context.Context, addr netapi.Address) (net.Conn, error) { 74 return h.dialer.Conn(ctx, h.dispatchAddr(ctx, addr)) 75 } 76 77 func (h *Hosts) PacketConn(ctx context.Context, addr netapi.Address) (net.PacketConn, error) { 78 c, err := h.dialer.PacketConn(ctx, h.dispatchAddr(ctx, addr)) 79 if err != nil { 80 return nil, err 81 } 82 return &dispatchPacketConn{c, h.dispatchAddr}, nil 83 } 84 85 func (h *Hosts) dispatchAddr(ctx context.Context, addr netapi.Address) netapi.Address { 86 v, ok := h.hosts[addr.Hostname()] 87 if !ok { 88 return addr 89 } 90 91 if v.portMap != nil { 92 z, ok := v.portMap[addr.Port().Port()] 93 if ok { 94 store := netapi.StoreFromContext(ctx) 95 store.Add("Hosts", addr.String()) 96 addr = addr.OverrideHostname(z.Hostname()).OverridePort(z.Port()) 97 store.Add(netapi.CurrentKey{}, addr) 98 return addr 99 } 100 } 101 102 if v.V == nil { 103 return addr 104 } 105 106 netapi.StoreFromContext(ctx). 107 Add("Hosts", addr.Hostname()). 108 Add(netapi.CurrentKey{}, addr) 109 return addr.OverrideHostname(v.V.Hostname()) 110 111 } 112 113 func (h *Hosts) LookupIP(ctx context.Context, domain string, opts ...func(*netapi.LookupIPOption)) ([]net.IP, error) { 114 addr := h.dispatchAddr(ctx, netapi.ParseAddressPort(0, domain, netapi.EmptyPort)) 115 if addr.Type() == netapi.IP { 116 return []net.IP{yerror.Ignore(addr.IP(ctx))}, nil 117 } 118 119 return h.resolver.LookupIP(ctx, addr.Hostname(), opts...) 120 } 121 122 func (h *Hosts) Raw(ctx context.Context, req dnsmessage.Question) (dnsmessage.Message, error) { 123 addr := h.dispatchAddr(ctx, netapi.ParseAddressPort(0, strings.TrimSuffix(req.Name.String(), "."), netapi.EmptyPort)) 124 if req.Type != dnsmessage.TypeAAAA && req.Type != dnsmessage.TypeA { 125 return h.resolver.Raw(ctx, req) 126 } 127 128 if addr.Type() != netapi.IP { 129 name, err := dnsmessage.NewName(addr.Hostname() + ".") 130 if err != nil { 131 return dnsmessage.Message{}, err 132 } 133 req.Name = name 134 return h.resolver.Raw(ctx, req) 135 } 136 137 msg := dnsmessage.Message{ 138 Header: dnsmessage.Header{ 139 ID: 0, 140 Response: true, 141 Authoritative: false, 142 RecursionDesired: false, 143 RCode: dnsmessage.RCodeSuccess, 144 RecursionAvailable: false, 145 }, 146 Questions: []dnsmessage.Question{ 147 { 148 Name: req.Name, 149 Type: req.Type, 150 Class: dnsmessage.ClassINET, 151 }, 152 }, 153 } 154 155 if req.Type == dnsmessage.TypeAAAA { 156 msg.Answers = []dnsmessage.Resource{ 157 { 158 Header: dnsmessage.ResourceHeader{ 159 Name: req.Name, 160 Class: dnsmessage.ClassINET, 161 TTL: 600, 162 Type: dnsmessage.TypeAAAA, 163 }, 164 Body: &dnsmessage.AAAAResource{AAAA: [16]byte(yerror.Ignore(addr.IP(ctx)).To16())}, 165 }, 166 } 167 } 168 169 if req.Type == dnsmessage.TypeA { 170 msg.Answers = []dnsmessage.Resource{ 171 { 172 Header: dnsmessage.ResourceHeader{ 173 Name: req.Name, 174 Class: dnsmessage.ClassINET, 175 TTL: 600, 176 Type: dnsmessage.TypeA, 177 }, 178 Body: &dnsmessage.AResource{A: [4]byte(yerror.Ignore(addr.IP(ctx)).To4())}, 179 }, 180 } 181 } 182 183 return msg, nil 184 } 185 186 func (h *Hosts) Close() error { return nil }