-
Notifications
You must be signed in to change notification settings - Fork 4.9k
DNS: Fix some bugs; Refactors; Optimizations #4659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
感谢 PR,我对 @patterniha 的能力还是有一些信心的,所以 #4661 (comment) ,今天或明天我发个四月累积更新版本让用户测试 |
|
Thank you very much for trusting me. |
|
I need finalQuery |
|
This reverts commit aa4134f
好明显的瑕疵,果然没有人 review 过 |
|
i just put cache-related-codes to "cache_controller.go" file, and just copied the codes. so your comment is not related to this PR, if you want to fix it you can fix it in one your open PR, or open new PR for that. |
similar to #4611 but new-features removed.
so, after this PR merged, i open new PR for new-features.
fixed bugs and refactor and optimization are related and cannot be separated further.
Fixed bugs:
When the cache is disabled (
disableCache = true), instead of not using the cache and sending a new IP-query, it both uses the cache and sends new IP-Query!This is because the order of the codes in nameserver_xxx-QueryIP function is wrong and the
ips, ttl, err := s.findIPsForDomain(fqdn, option)should be afterselect-casecode. linkalso we should not use
forloop for this part of code.Suppose dialing a dns-server is unsuccessful(for tcp/quic base DNS)[for example receiving rst-ack after sending syn or receiving http-error response for doh], Instead of immediately returning an error and trying the next DNS-server-fallback, it waits until the timeout ends and then tries the next fallback!
When ipOption.IPv4Enable and ipOption.IPv6Enable are both true, two IP-Query(A, AAAA) are sent and it waits for both responses to be received, then it merges the responses and returns, but suppose only AAAA-response is received and in the meantime, another request comes, while the first request is still waiting for A-response, For the second request, since AAAA-record is in the cache, it uses the cache and incorrectly only v6-IPs is returned for the second request! while the second request must wait for A-response like the first request.
also, suppose the A-record expire sooner than AAAA-record, so So until AAAA-record expires we only have IPv6!
also, suppose we receive only AAAA-response and the A-response dropped for a request,
so for all subsequent requests and for 600 seconds we only have ipv6! and if our network is IPv4 only, for 600 seconds we cannot access internet!!!
this problem affect internal usage of built-in-DNS (for example domainStrategy = "UseIP" or domainStrategy = "IPOnDemand" for routing) but not affect client/browser request, because for client/browser IP-request we have two distinct request for IPv4 and IPv6(pass through dns-proxy) but for UseIP/IPOnDemand requests we have one merged request, and this bug only affect merged requests.
when IP-record-until-expire-time is less than 1 seconds and the IP-list is not empty, it returns IPs with
TTL = 0but we shouldn't set record-TTL to 0. The number 0 is not defined in the standard, and it may cause DNS information to be ignored or rejected,so after converting to
uint32, It should be rounded up, not down. linkthe
IsOwnLinkfunction in "app > dns > dns.go" not updated after adding tag for each DNS-server.instead of creating new
GeoIPMatcherContainerin "dns.go" we should useGlobalGeoIPContainerto reduce memory usage.GeoIPMatcherContaineris implemented to reduce memory usage, so we should only have one instance ofGeoIPMatcherContainerin the entire code.when no IPs match
expectedIPs, we should returnErrEmptyResponseinstead oferrExpectedIPNonMatch,otherwise, DNS-proxy send no response to client/browser DNS-query.
in
multi_error.go > AllEqualerrors compare with == instead of errors.Is !CleanUPtask should start(check-executed) inaddPendingRequestfunction in nameserver_udp.gorefactor:
Most codes in nameserver files are duplicated,
Cleanup,findIPsForDomain,updateIP, ...These functions control how to read and write in the cache.
so I add
CacheControllerstruct to implement these functions in one place, and each tcp/quic/udp/doh-NameServer struct has aCacheController.So now the codes are standard, and these function are only written once.
optimization:
Also, some optimizations have been made which are clear in the code and do not need to be explained.
for example in
Xray-core/app/dns/nameserver.go
Line 201 in a608c5a
you pass
c.clientIPanddisableCacheas function arguments, but these are fixed-options and should not pass as function arguments each time "QueryIP" call.