Add built-in support for Tor
This commit is contained in:
parent
977dcad826
commit
0166f21b27
|
@ -47,7 +47,7 @@ func PrefixWithSize(packet []byte) ([]byte, error) {
|
|||
return packet, nil
|
||||
}
|
||||
|
||||
func ReadPrefixed(conn *net.TCPConn) ([]byte, error) {
|
||||
func ReadPrefixed(conn *net.Conn) ([]byte, error) {
|
||||
buf := make([]byte, 2+MaxDNSPacketSize)
|
||||
packetLength, pos := -1, 0
|
||||
for {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
@ -15,6 +16,7 @@ import (
|
|||
"github.com/BurntSushi/toml"
|
||||
"github.com/jedisct1/dlog"
|
||||
stamps "github.com/jedisct1/go-dnsstamps"
|
||||
netproxy "golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
|
@ -27,6 +29,7 @@ type Config struct {
|
|||
ForceTCP bool `toml:"force_tcp"`
|
||||
Timeout int `toml:"timeout"`
|
||||
KeepAlive int `toml:"keepalive"`
|
||||
Proxy string `toml:"proxy"`
|
||||
CertRefreshDelay int `toml:"cert_refresh_delay"`
|
||||
CertIgnoreTimestamp bool `toml:"cert_ignore_timestamp"`
|
||||
EphemeralKeys bool `toml:"dnscrypt_ephemeral_keys"`
|
||||
|
@ -237,6 +240,19 @@ func ConfigLoad(proxy *Proxy, svcFlag *string) error {
|
|||
proxy.xTransport.useIPv4 = config.SourceIPv4
|
||||
proxy.xTransport.useIPv6 = config.SourceIPv6
|
||||
proxy.xTransport.keepAlive = time.Duration(config.KeepAlive) * time.Second
|
||||
|
||||
if len(config.Proxy) > 0 {
|
||||
proxyDialerURL, err := url.Parse(config.Proxy)
|
||||
if err != nil {
|
||||
dlog.Fatalf("Unable to parse proxy url [%v]", config.Proxy)
|
||||
}
|
||||
proxyDialer, err := netproxy.FromURL(proxyDialerURL, netproxy.Direct)
|
||||
if err != nil {
|
||||
dlog.Fatalf("Unable to use the proxy: [%v]", err)
|
||||
}
|
||||
proxy.xTransport.proxyDialer = &proxyDialer
|
||||
}
|
||||
|
||||
proxy.xTransport.rebuildTransport()
|
||||
|
||||
proxy.timeout = time.Duration(config.Timeout) * time.Millisecond
|
||||
|
|
|
@ -77,6 +77,14 @@ require_nofilter = true
|
|||
force_tcp = false
|
||||
|
||||
|
||||
## HTTP / SOCKS proxy
|
||||
## Uncomment the following line to route all TCP connections to a local Tor node
|
||||
## Tor doesn't support UDP, so set `force_tcp` to `true` as well.
|
||||
|
||||
# proxy = "socks5://127.0.0.1:9050"
|
||||
|
||||
|
||||
|
||||
## How long a DNS query will wait for a response, in milliseconds
|
||||
|
||||
timeout = 2500
|
||||
|
|
|
@ -176,7 +176,7 @@ func (proxy *Proxy) tcpListener(acceptPc *net.TCPListener) {
|
|||
}
|
||||
defer proxy.clientsCountDec()
|
||||
clientPc.SetDeadline(time.Now().Add(proxy.timeout))
|
||||
packet, err := ReadPrefixed(clientPc.(*net.TCPConn))
|
||||
packet, err := ReadPrefixed(&clientPc)
|
||||
if err != nil || len(packet) < MinDNSPacketSize {
|
||||
return
|
||||
}
|
||||
|
@ -214,22 +214,29 @@ func (proxy *Proxy) exchangeWithUDPServer(serverInfo *ServerInfo, sharedKey *[32
|
|||
}
|
||||
|
||||
func (proxy *Proxy) exchangeWithTCPServer(serverInfo *ServerInfo, sharedKey *[32]byte, encryptedQuery []byte, clientNonce []byte) ([]byte, error) {
|
||||
pc, err := net.DialTCP("tcp", nil, serverInfo.TCPAddr)
|
||||
proxyDialer := proxy.xTransport.proxyDialer
|
||||
var pc *net.Conn
|
||||
if proxyDialer == nil {
|
||||
pcx, err := net.DialTCP("tcp", nil, serverInfo.TCPAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pc = interface{}(pcx).(*net.Conn)
|
||||
} else {
|
||||
pcx, err := (*proxyDialer).Dial("tcp", serverInfo.TCPAddr.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pc = &pcx
|
||||
}
|
||||
(*pc).SetDeadline(time.Now().Add(serverInfo.Timeout))
|
||||
encryptedQuery, err := PrefixWithSize(encryptedQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pc.SetDeadline(time.Now().Add(serverInfo.Timeout))
|
||||
encryptedQuery, err = PrefixWithSize(encryptedQuery)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pc.Write(encryptedQuery)
|
||||
|
||||
(*pc).Write(encryptedQuery)
|
||||
encryptedResponse, err := ReadPrefixed(pc)
|
||||
pc.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
(*pc).Close()
|
||||
return proxy.Decrypt(serverInfo, sharedKey, encryptedResponse, clientNonce)
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
stamps "github.com/jedisct1/go-dnsstamps"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/http2"
|
||||
netproxy "golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
const DefaultFallbackResolver = "9.9.9.9:53"
|
||||
|
@ -41,6 +42,7 @@ type XTransport struct {
|
|||
useIPv6 bool
|
||||
tlsDisableSessionTickets bool
|
||||
tlsCipherSuite []uint16
|
||||
proxyDialer *netproxy.Dialer
|
||||
}
|
||||
|
||||
var DefaultKeepAlive = 5 * time.Second
|
||||
|
@ -74,7 +76,6 @@ func (xTransport *XTransport) rebuildTransport() {
|
|||
(*xTransport.transport).CloseIdleConnections()
|
||||
}
|
||||
timeout := xTransport.timeout
|
||||
dialer := &net.Dialer{Timeout: timeout, KeepAlive: timeout, DualStack: true}
|
||||
transport := &http.Transport{
|
||||
DisableKeepAlives: false,
|
||||
DisableCompression: true,
|
||||
|
@ -95,7 +96,12 @@ func (xTransport *XTransport) rebuildTransport() {
|
|||
dlog.Debugf("[%s] IP address was not cached", host)
|
||||
}
|
||||
addrStr = ipOnly + ":" + strconv.Itoa(port)
|
||||
return dialer.DialContext(ctx, network, addrStr)
|
||||
if xTransport.proxyDialer == nil {
|
||||
dialer := &net.Dialer{Timeout: timeout, KeepAlive: timeout, DualStack: true}
|
||||
return dialer.DialContext(ctx, network, addrStr)
|
||||
} else {
|
||||
return (*xTransport.proxyDialer).Dial(network, addrStr)
|
||||
}
|
||||
},
|
||||
}
|
||||
if xTransport.tlsDisableSessionTickets || xTransport.tlsCipherSuite != nil {
|
||||
|
|
Loading…
Reference in New Issue