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
|
return packet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadPrefixed(conn *net.TCPConn) ([]byte, error) {
|
func ReadPrefixed(conn *net.Conn) ([]byte, error) {
|
||||||
buf := make([]byte, 2+MaxDNSPacketSize)
|
buf := make([]byte, 2+MaxDNSPacketSize)
|
||||||
packetLength, pos := -1, 0
|
packetLength, pos := -1, 0
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -15,6 +16,7 @@ import (
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/jedisct1/dlog"
|
"github.com/jedisct1/dlog"
|
||||||
stamps "github.com/jedisct1/go-dnsstamps"
|
stamps "github.com/jedisct1/go-dnsstamps"
|
||||||
|
netproxy "golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -27,6 +29,7 @@ type Config struct {
|
||||||
ForceTCP bool `toml:"force_tcp"`
|
ForceTCP bool `toml:"force_tcp"`
|
||||||
Timeout int `toml:"timeout"`
|
Timeout int `toml:"timeout"`
|
||||||
KeepAlive int `toml:"keepalive"`
|
KeepAlive int `toml:"keepalive"`
|
||||||
|
Proxy string `toml:"proxy"`
|
||||||
CertRefreshDelay int `toml:"cert_refresh_delay"`
|
CertRefreshDelay int `toml:"cert_refresh_delay"`
|
||||||
CertIgnoreTimestamp bool `toml:"cert_ignore_timestamp"`
|
CertIgnoreTimestamp bool `toml:"cert_ignore_timestamp"`
|
||||||
EphemeralKeys bool `toml:"dnscrypt_ephemeral_keys"`
|
EphemeralKeys bool `toml:"dnscrypt_ephemeral_keys"`
|
||||||
|
@ -237,6 +240,19 @@ func ConfigLoad(proxy *Proxy, svcFlag *string) error {
|
||||||
proxy.xTransport.useIPv4 = config.SourceIPv4
|
proxy.xTransport.useIPv4 = config.SourceIPv4
|
||||||
proxy.xTransport.useIPv6 = config.SourceIPv6
|
proxy.xTransport.useIPv6 = config.SourceIPv6
|
||||||
proxy.xTransport.keepAlive = time.Duration(config.KeepAlive) * time.Second
|
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.xTransport.rebuildTransport()
|
||||||
|
|
||||||
proxy.timeout = time.Duration(config.Timeout) * time.Millisecond
|
proxy.timeout = time.Duration(config.Timeout) * time.Millisecond
|
||||||
|
|
|
@ -77,6 +77,14 @@ require_nofilter = true
|
||||||
force_tcp = false
|
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
|
## How long a DNS query will wait for a response, in milliseconds
|
||||||
|
|
||||||
timeout = 2500
|
timeout = 2500
|
||||||
|
|
|
@ -176,7 +176,7 @@ func (proxy *Proxy) tcpListener(acceptPc *net.TCPListener) {
|
||||||
}
|
}
|
||||||
defer proxy.clientsCountDec()
|
defer proxy.clientsCountDec()
|
||||||
clientPc.SetDeadline(time.Now().Add(proxy.timeout))
|
clientPc.SetDeadline(time.Now().Add(proxy.timeout))
|
||||||
packet, err := ReadPrefixed(clientPc.(*net.TCPConn))
|
packet, err := ReadPrefixed(&clientPc)
|
||||||
if err != nil || len(packet) < MinDNSPacketSize {
|
if err != nil || len(packet) < MinDNSPacketSize {
|
||||||
return
|
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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pc.SetDeadline(time.Now().Add(serverInfo.Timeout))
|
pc = interface{}(pcx).(*net.Conn)
|
||||||
encryptedQuery, err = PrefixWithSize(encryptedQuery)
|
} else {
|
||||||
|
pcx, err := (*proxyDialer).Dial("tcp", serverInfo.TCPAddr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pc.Write(encryptedQuery)
|
pc = &pcx
|
||||||
|
}
|
||||||
|
(*pc).SetDeadline(time.Now().Add(serverInfo.Timeout))
|
||||||
|
encryptedQuery, err := PrefixWithSize(encryptedQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
(*pc).Write(encryptedQuery)
|
||||||
encryptedResponse, err := ReadPrefixed(pc)
|
encryptedResponse, err := ReadPrefixed(pc)
|
||||||
pc.Close()
|
(*pc).Close()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return proxy.Decrypt(serverInfo, sharedKey, encryptedResponse, clientNonce)
|
return proxy.Decrypt(serverInfo, sharedKey, encryptedResponse, clientNonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
stamps "github.com/jedisct1/go-dnsstamps"
|
stamps "github.com/jedisct1/go-dnsstamps"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
netproxy "golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultFallbackResolver = "9.9.9.9:53"
|
const DefaultFallbackResolver = "9.9.9.9:53"
|
||||||
|
@ -41,6 +42,7 @@ type XTransport struct {
|
||||||
useIPv6 bool
|
useIPv6 bool
|
||||||
tlsDisableSessionTickets bool
|
tlsDisableSessionTickets bool
|
||||||
tlsCipherSuite []uint16
|
tlsCipherSuite []uint16
|
||||||
|
proxyDialer *netproxy.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultKeepAlive = 5 * time.Second
|
var DefaultKeepAlive = 5 * time.Second
|
||||||
|
@ -74,7 +76,6 @@ func (xTransport *XTransport) rebuildTransport() {
|
||||||
(*xTransport.transport).CloseIdleConnections()
|
(*xTransport.transport).CloseIdleConnections()
|
||||||
}
|
}
|
||||||
timeout := xTransport.timeout
|
timeout := xTransport.timeout
|
||||||
dialer := &net.Dialer{Timeout: timeout, KeepAlive: timeout, DualStack: true}
|
|
||||||
transport := &http.Transport{
|
transport := &http.Transport{
|
||||||
DisableKeepAlives: false,
|
DisableKeepAlives: false,
|
||||||
DisableCompression: true,
|
DisableCompression: true,
|
||||||
|
@ -95,7 +96,12 @@ func (xTransport *XTransport) rebuildTransport() {
|
||||||
dlog.Debugf("[%s] IP address was not cached", host)
|
dlog.Debugf("[%s] IP address was not cached", host)
|
||||||
}
|
}
|
||||||
addrStr = ipOnly + ":" + strconv.Itoa(port)
|
addrStr = ipOnly + ":" + strconv.Itoa(port)
|
||||||
|
if xTransport.proxyDialer == nil {
|
||||||
|
dialer := &net.Dialer{Timeout: timeout, KeepAlive: timeout, DualStack: true}
|
||||||
return dialer.DialContext(ctx, network, addrStr)
|
return dialer.DialContext(ctx, network, addrStr)
|
||||||
|
} else {
|
||||||
|
return (*xTransport.proxyDialer).Dial(network, addrStr)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if xTransport.tlsDisableSessionTickets || xTransport.tlsCipherSuite != nil {
|
if xTransport.tlsDisableSessionTickets || xTransport.tlsCipherSuite != nil {
|
||||||
|
|
Loading…
Reference in New Issue