fix/optimize: reroute if necessary and add opendns as bootstrap dns

This commit is contained in:
mzz2017 2023-04-07 20:38:06 +08:00
parent efacd08910
commit 127a000058
5 changed files with 35 additions and 8 deletions

View File

@ -28,6 +28,8 @@ var (
systemDnsNextUpdateAfter time.Time
BadDnsAnsError = fmt.Errorf("bad dns answer")
BootstrapDns = netip.MustParseAddrPort("208.67.222.222:5353")
)
func TryUpdateSystemDns() (err error) {
@ -61,7 +63,17 @@ func tryUpdateSystemDns() (err error) {
err = fmt.Errorf("no valid dns server in /etc/resolv.conf")
return err
}
systemDns = netip.MustParseAddrPort(dnsConf.servers[0])
systemDns = netip.AddrPort{}
for _, s := range dnsConf.servers {
ipPort := netip.MustParseAddrPort(s)
if !ipPort.Addr().IsLoopback() {
systemDns = ipPort
break
}
}
if !systemDns.IsValid() {
systemDns = BootstrapDns
}
return nil
}

View File

@ -92,7 +92,7 @@ func NewUpstream(ctx context.Context, upstream *url.URL) (up *Upstream, err erro
return nil, fmt.Errorf("failed to resolve dns_upstream: %w", err)
}
if !ip46.Ip4.IsValid() && !ip46.Ip6.IsValid() {
return nil, fmt.Errorf("dns_upstream has no record")
return nil, fmt.Errorf("dns_upstream %v has no record", upstream.String())
}
return &Upstream{

View File

@ -491,8 +491,8 @@ func (c *ControlPlane) dnsUpstreamReadyCallback(dnsUpstream *dns.Upstream) (err
return nil
}
func (c *ControlPlane) ChooseDialTarget(outbound consts.OutboundIndex, dst netip.AddrPort, domain string) (dialTarget string, dialMode consts.DialMode) {
dialMode = consts.DialMode_Ip
func (c *ControlPlane) ChooseDialTarget(outbound consts.OutboundIndex, dst netip.AddrPort, domain string) (dialTarget string, shouldReroute bool) {
dialMode := consts.DialMode_Ip
if !outbound.IsReserved() && domain != "" {
switch c.dialMode {
@ -521,6 +521,9 @@ func (c *ControlPlane) ChooseDialTarget(outbound consts.OutboundIndex, dst netip
c.muRealDomainSet.Lock()
c.realDomainSet.AddString(domain)
c.muRealDomainSet.Unlock()
// Should use this domain to reroute
shouldReroute = true
}
}
}
@ -553,7 +556,7 @@ func (c *ControlPlane) ChooseDialTarget(outbound consts.OutboundIndex, dst netip
"to": dialTarget,
}).Debugln("Rewrite dial target to domain")
}
return dialTarget, dialMode
return dialTarget, shouldReroute
}
type Listener struct {
@ -758,7 +761,7 @@ func (c *ControlPlane) chooseBestDnsDialer(
default:
return nil, fmt.Errorf("unexpected ipversion: %v", ver)
}
outboundIndex, mark, _, err := c.Route(req.realSrc, netip.AddrPortFrom(dAddr, dnsUpstream.Port), "", proto.ToL4ProtoType(), req.routingResult)
outboundIndex, mark, _, err := c.Route(req.realSrc, netip.AddrPortFrom(dAddr, dnsUpstream.Port), dnsUpstream.Hostname, proto.ToL4ProtoType(), req.routingResult)
if err != nil {
return nil, err
}

View File

@ -68,6 +68,11 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
outboundIndex = consts.OutboundControlPlaneRouting
}
dialTarget, shouldReroute := c.ChooseDialTarget(outboundIndex, dst, domain)
if shouldReroute {
outboundIndex = consts.OutboundControlPlaneRouting
}
switch outboundIndex {
case consts.OutboundDirect:
case consts.OutboundControlPlaneRouting:
@ -82,6 +87,8 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
outboundIndex.String(),
)
}
// Reset dialTarget.
dialTarget, _ = c.ChooseDialTarget(outboundIndex, dst, domain)
default:
}
// TODO: Set-up ip to domain mapping and show domain if possible.
@ -99,7 +106,6 @@ func (c *ControlPlane) handleConn(lConn net.Conn) (err error) {
return fmt.Errorf("failed to select dialer from group %v (%v): %w", outbound.Name, networkType.String(), err)
}
dialTarget, _ := c.ChooseDialTarget(outboundIndex, dst, domain)
if c.log.IsLevelEnabled(logrus.InfoLevel) {
c.log.WithFields(logrus.Fields{
"network": networkType.String(),

View File

@ -143,6 +143,11 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
outboundIndex = consts.OutboundControlPlaneRouting
}
dialTarget, shouldReroute := c.ChooseDialTarget(outboundIndex, realDst, domain)
if shouldReroute {
outboundIndex = consts.OutboundControlPlaneRouting
}
if routingResult.Must > 0 {
isDns = false // Regard as plain traffic.
}
@ -164,6 +169,8 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
outboundIndex.String(),
)
}
// Reset dialTarget.
dialTarget, _ = c.ChooseDialTarget(outboundIndex, realDst, domain)
default:
}
if isDns {
@ -197,7 +204,6 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
// 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.
// However, games may not use QUIC for communication, thus we cannot use domain to dial, which is fine.
dialTarget, _ := c.ChooseDialTarget(outboundIndex, realDst, domain)
// Get udp endpoint.
var ue *UdpEndpoint