xvzc / SpoofDPI

A simple and fast anti-censorship tool written in Go
Apache License 2.0
3.53k stars 251 forks source link

Option to disable built-in DNS resolver & use system DNS #31

Closed lepz0r closed 2 months ago

lepz0r commented 2 years ago

For users that already use encrypted DNS resolver like dnscrypt-proxy & stubby

jckefan commented 2 years ago

OMG! Yes, I also was about to make the same feature request!

xvzc commented 2 years ago

is this like the same request as #32 ?

lepz0r commented 2 years ago

is this like the same request as #32 ?

I think it's different, #32 allows you to specify DoH's resolver template while this request allows you to completely disable DoH & use system's DNS

xvzc commented 2 years ago

so, do you guys locally have your own dns severs ?

xvzc commented 2 years ago

should i add an option like --use-system-proxy or what kinda option would it be?

lepz0r commented 2 years ago

should i add an option like --use-system-proxy or what kinda option would it be?

--use-system-dns would be good for this feature

xvzc commented 2 years ago

i meant it either. just mistyped

xvzc commented 2 years ago

okay, then let me take a look on it

r3a1d3a1 commented 1 year ago

A simple hack in the meantime. Replace the dns.go file contents in the doh folder with this:

package doh

import (
    dns "github.com/Focinfi/go-dns-resolver"

    "errors"
    "regexp"
)

func Init() {
    dns.Config.SetTimeout(uint(5))
    dns.Config.RetryTimes = uint(2)
}

func Lookup(domain string) (string, error) {
    ipRegex := "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"

    if r, _ := regexp.MatchString(ipRegex, domain); r {
        return domain, nil
    }

    if results, err := dns.Exchange(domain, "127.0.0.1:53", dns.TypeA); err == nil {
        if len(results) < 1 {
            return "", errors.New(" couldn't resolve the domain")
        }
        return results[0].Content, nil
    } else {
        return "", err
    }
}

N.B. change '127.0.0.1:53' to point to your local DNS server.

vukitoso commented 1 year ago

How can I disable DOH and use a local DNS server on port 53?

nokia8801 commented 8 months ago

Please add an option for this. I too use dnscrpyt-proxy with a custom configuration and blocklist/whitelist and I can't get this and it to work together. Something like a --use-system-dns switch would be great.

MahouShoujoMivutilde commented 2 months ago

Yeah, an option to specify some custom plain text DNS would be much welcome.

But making it support any address:port for plain text DNS as opposed to system DNS exclusively would be more flexible and thus preferable.

Although system DNS would much be simpler to implement: net.LookupHost("www.youtube.com").


BTW, Updated doh/dns.go like the above, but now it works fine with www.youtube.com and everything else that returns CNAME and a bunch of ips with it. It also now respects the --dns argument.

New plain text DNS code

```go // replace ./doh/dns.go with this package doh import ( "errors" "fmt" "net" "regexp" // NOTE: This library has some issues with CNAMEs // repro: // try to resolve `www.youtube.com` with both this and `dog www.youtube.com A` // // go-dns-resolver: first A record is empty string // dog: first A record is actually CNAME youtube-ui.l.google.com. // the rest is the same DNS "github.com/Focinfi/go-dns-resolver" ) var plainDnsAddr string func Init(dns string) { // honor the provided dns, just avoid DoH plainDnsAddr = dns DNS.Config.SetTimeout(uint(5)) DNS.Config.RetryTimes = uint(2) } func Lookup(domain string) (string, error) { ipRegex := "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" if r, _ := regexp.MatchString(ipRegex, domain); r { return domain, nil } if results, err := DNS.Exchange(domain, fmt.Sprintf("%s:53", plainDnsAddr), DNS.TypeA); err == nil { if len(results) < 1 { return "", errors.New(" couldn't resolve the domain") } for _, r := range results { // return first valid ip address if net.ParseIP(r.Content) != nil { return r.Content, nil } } return "", errors.New(" BUG: resolved the domain, but no ip records found (all CNAMEs?)") } else { return "", err } } ```

Wait, what was even wrong with it?

Demo of the problem

```go package main import ( "fmt" dns "github.com/Focinfi/go-dns-resolver" ) func main() { dns.Config.SetTimeout(uint(2)) dns.Config.RetryTimes = uint(4) if results, err := dns.Exchange("www.youtube.com", "1.1.1.1:53", dns.TypeA); err == nil { for _, r := range results { fmt.Println(r.Record, r.Type, r.Ttl, r.Priority, r.Content) } fmt.Printf("results[0].Content = `%s`\n", results[0].Content) } else { panic(err) } } ``` Results in ``` ❯ go run ./main.go www.youtube.com A 0s 0 www.youtube.com A 0s 0 www.youtube.com A 4m53s 0 74.125.131.198 results[0].Content = `` ``` Notice how first record is an empty string (**proxy would fail to connect to it!**). That's because it's a CNAME! ``` ❯ dog @1.1.1.1 www.youtube.com CNAME www.youtube.com. 5m00s "youtube-ui.l.google.com." CNAME youtube-ui.l.google.com. 5m00s "wide-youtube.l.google.com." A wide-youtube.l.google.com. 5m00s 142.251.1.198 ``` Why is it in A records is a question for github.com/Focinfi/go-dns-resolver.

With the updated code instead of using the first element which is presumed (incorrectly) to be a valid A record we look for first valid ip instead and return that.


As a side note:

Holy shit the dependencies of this repo are so outdated.

xvzc commented 2 months ago

Okay guys I got some time to maintain this repository now. I think i should two options that is like --dns-addr --dns-port

Would these two options meet you guys' requirements?

And thanks to @MahouShoujoMivutilde, i will take a look at the issue that you talked about and I'll upgrade the dependencies :)

xvzc commented 2 months ago

Closed as completed

MahouShoujoMivutilde commented 2 months ago

Thank you!