diff --git a/common/dns/dns.go b/common/dns/dns.go index f53a83a2..7ec6f30b 100644 --- a/common/dns/dns.go +++ b/common/dns/dns.go @@ -1,7 +1,6 @@ package dns import ( - "encoding/binary" "net" ) @@ -17,23 +16,12 @@ type DnsCache interface { } type FakeDns interface { - // GenerateFakeResponse generates a response for the specify request with a fake IP address. + // GenerateFakeResponse generates a fake dns response for the specify request. GenerateFakeResponse(request []byte) ([]byte, error) - // QueryDomain returns the corresponding domain for IP. + // QueryDomain returns the corresponding domain for the given IP. QueryDomain(ip net.IP) string -} - -const ( - // We set fake dns response ttl to 1, 256 fake ips should be suffice. - MinFakeIPCursor = 4043309056 // 241.0.0.0 - MaxFakeIPCursor = 4043309311 // 241.0.0.255 -) -func IsFakeIP(ip net.IP) bool { - n := binary.BigEndian.Uint32([]byte(ip)[net.IPv6len-net.IPv4len:]) - if n >= MinFakeIPCursor && n <= MaxFakeIPCursor { - return true - } - return false + // IsFakeIP checks if the given ip is a fake IP. + IsFakeIP(ip net.IP) bool } diff --git a/common/dns/fakedns/fakedns.go b/common/dns/fakedns/fakedns.go index ac97fb9a..8c966775 100644 --- a/common/dns/fakedns/fakedns.go +++ b/common/dns/fakedns/fakedns.go @@ -14,12 +14,25 @@ import ( "github.com/eycorsican/go-tun2socks/core" ) +const ( + // If fake dns response ttl is set to 1, 256 fake ips should be suffice. + MinFakeIPCursor uint32 = 0xf1000000 // 241.0.0.0 + MaxFakeIPCursor uint32 = 0xf10000ff // 241.0.0.255 + FakeResponseTtl uint32 = 1 // in sec +) + type simpleFakeDns struct { sync.Mutex // TODO cleanup map ip2domain map[uint32]string + + // Cursor is an IPv4 address represent in uint32 type. cursor uint32 + minCursor uint32 + maxCursor uint32 + + fakeTtl uint32 } func canHandleDnsQuery(data []byte) bool { @@ -53,11 +66,7 @@ func canHandleDnsQuery(data []byte) bool { } func uint322ip(n uint32) net.IP { - b1 := (n & 0xff000000) >> 24 - b2 := (n & 0x00ff0000) >> 16 - b3 := (n & 0x0000ff00) >> 8 - b4 := (n & 0x000000ff) - return net.IPv4(byte(b1), byte(b2), byte(b3), byte(b4)) + return net.IPv4(byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) } func ip2uint32(ip net.IP) uint32 { @@ -67,7 +76,7 @@ func ip2uint32(ip net.IP) uint32 { func NewSimpleFakeDns() cdns.FakeDns { return &simpleFakeDns{ ip2domain: make(map[uint32]string, 64), - cursor: cdns.MinFakeIPCursor, + cursor: MinFakeIPCursor, } } @@ -77,8 +86,8 @@ func (f *simpleFakeDns) allocateIP(domain string) net.IP { f.ip2domain[f.cursor] = domain ip := uint322ip(f.cursor) f.cursor += 1 - if f.cursor > cdns.MaxFakeIPCursor { - f.cursor = cdns.MinFakeIPCursor + if f.cursor > MaxFakeIPCursor { + f.cursor = MinFakeIPCursor } return ip } @@ -94,49 +103,56 @@ func (f *simpleFakeDns) QueryDomain(ip net.IP) string { } func (f *simpleFakeDns) GenerateFakeResponse(request []byte) ([]byte, error) { - if canHandleDnsQuery(request) { - req := new(dns.Msg) - req.Unpack(request) - qtype := req.Question[0].Qtype - fqdn := req.Question[0].Name - domain := fqdn[:len(fqdn)-1] - ip := f.allocateIP(domain) - log.Debugf("fake dns allocated ip %v for domain %v", ip, domain) - resp := new(dns.Msg) - resp = resp.SetReply(req) - if qtype == dns.TypeA { - resp.Answer = append(resp.Answer, &dns.A{ - Hdr: dns.RR_Header{ - Name: fqdn, - Rrtype: dns.TypeA, - Class: dns.ClassINET, - Ttl: 1, - Rdlength: net.IPv4len, - }, - A: ip, - }) - } else if qtype == dns.TypeAAAA { - resp.Answer = append(resp.Answer, &dns.AAAA{ - Hdr: dns.RR_Header{ - Name: fqdn, - Rrtype: dns.TypeAAAA, - Class: dns.ClassINET, - Ttl: 1, - Rdlength: net.IPv6len, - }, - AAAA: ip, - }) - } else { - return nil, fmt.Errorf("unexcepted dns qtype %v", qtype) - } - buf := core.NewBytes(core.BufSize) - defer core.FreeBytes(buf) - dnsAnswer, err := resp.PackBuffer(buf) - if err != nil { - return nil, fmt.Errorf("failed to pack dns answer: %v", err) - } - return append([]byte(nil), dnsAnswer...), nil - } else { + if !canHandleDnsQuery(request) { return nil, errors.New("cannot handle DNS request") } + req := new(dns.Msg) + req.Unpack(request) + qtype := req.Question[0].Qtype + fqdn := req.Question[0].Name + domain := fqdn[:len(fqdn)-1] + ip := f.allocateIP(domain) + log.Debugf("fake dns allocated ip %v for domain %v", ip, domain) + resp := new(dns.Msg) + resp = resp.SetReply(req) + if qtype == dns.TypeA { + resp.Answer = append(resp.Answer, &dns.A{ + Hdr: dns.RR_Header{ + Name: fqdn, + Rrtype: dns.TypeA, + Class: dns.ClassINET, + Ttl: FakeResponseTtl, + Rdlength: net.IPv4len, + }, + A: ip, + }) + } else if qtype == dns.TypeAAAA { + resp.Answer = append(resp.Answer, &dns.AAAA{ + Hdr: dns.RR_Header{ + Name: fqdn, + Rrtype: dns.TypeAAAA, + Class: dns.ClassINET, + Ttl: FakeResponseTtl, + Rdlength: net.IPv6len, + }, + AAAA: ip, + }) + } else { + return nil, fmt.Errorf("unexcepted dns qtype %v", qtype) + } + buf := core.NewBytes(core.BufSize) + defer core.FreeBytes(buf) + dnsAnswer, err := resp.PackBuffer(buf) + if err != nil { + return nil, fmt.Errorf("failed to pack dns answer: %v", err) + } + return append([]byte(nil), dnsAnswer...), nil +} + +func (f *simpleFakeDns) IsFakeIP(ip net.IP) bool { + c := ip2uint32(ip) + if c >= MinFakeIPCursor && c <= MaxFakeIPCursor { + return true + } + return false } diff --git a/core/util.go b/core/addr.go similarity index 100% rename from core/util.go rename to core/addr.go diff --git a/core/connection.go b/core/conn.go similarity index 100% rename from core/connection.go rename to core/conn.go diff --git a/proxy/shadowsocks/tcp.go b/proxy/shadowsocks/tcp.go index 3887ccb6..57571d44 100644 --- a/proxy/shadowsocks/tcp.go +++ b/proxy/shadowsocks/tcp.go @@ -72,7 +72,7 @@ func (h *tcpHandler) Connect(conn core.TCPConn, target net.Addr) error { var targetHost string = host if h.fakeDns != nil { if ip := net.ParseIP(host); ip != nil { - if dns.IsFakeIP(ip) { + if h.fakeDns.IsFakeIP(ip) { targetHost = h.fakeDns.QueryDomain(ip) } } diff --git a/proxy/shadowsocks/udp.go b/proxy/shadowsocks/udp.go index 74dddf64..9c31301b 100644 --- a/proxy/shadowsocks/udp.go +++ b/proxy/shadowsocks/udp.go @@ -154,7 +154,7 @@ func (h *udpHandler) DidReceiveTo(conn core.UDPConn, data []byte, addr net.Addr) var targetHost string = host if h.fakeDns != nil { if ip := net.ParseIP(host); ip != nil { - if dns.IsFakeIP(ip) { + if h.fakeDns.IsFakeIP(ip) { targetHost = h.fakeDns.QueryDomain(ip) } } diff --git a/proxy/socks/tcp.go b/proxy/socks/tcp.go index f10fb927..5bd8dca8 100644 --- a/proxy/socks/tcp.go +++ b/proxy/socks/tcp.go @@ -74,7 +74,7 @@ func (h *tcpHandler) Connect(conn core.TCPConn, target net.Addr) error { var targetHost string = host if h.fakeDns != nil { if ip := net.ParseIP(host); ip != nil { - if dns.IsFakeIP(ip) { + if h.fakeDns.IsFakeIP(ip) { targetHost = h.fakeDns.QueryDomain(ip) } } diff --git a/proxy/socks/udp.go b/proxy/socks/udp.go index f696a7b0..3db0a487 100644 --- a/proxy/socks/udp.go +++ b/proxy/socks/udp.go @@ -118,7 +118,7 @@ func (h *udpHandler) Connect(conn core.UDPConn, target net.Addr) error { return nil // skip dns } if ip := net.ParseIP(host); ip != nil { - if dns.IsFakeIP(ip) { + if h.fakeDns.IsFakeIP(ip) { targetHost = h.fakeDns.QueryDomain(ip) } } @@ -249,7 +249,7 @@ func (h *udpHandler) DidReceiveTo(conn core.UDPConn, data []byte, addr net.Addr) var targetHost string = host if h.fakeDns != nil { if ip := net.ParseIP(host); ip != nil { - if dns.IsFakeIP(ip) { + if h.fakeDns.IsFakeIP(ip) { targetHost = h.fakeDns.QueryDomain(ip) } }