From 2822a9781ba2683c25cd9fd99eab9bf6939b2ffd Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Wed, 10 Jan 2018 12:01:49 +0100 Subject: [PATCH] Add a config file --- .gitignore | 5 +- dnscrypt-proxy/config.go | 83 ++++++++++++++++++++++ dnscrypt-proxy/dnscrypt-proxy.toml | 27 +++++++ dnscrypt-proxy/main.go | 109 +++++++++++++++++------------ 4 files changed, 176 insertions(+), 48 deletions(-) create mode 100644 dnscrypt-proxy/config.go create mode 100644 dnscrypt-proxy/dnscrypt-proxy.toml diff --git a/.gitignore b/.gitignore index e390aeb5..9fec4e17 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,6 @@ vendor .glide/ # Binaries -dnscrypt-proxy -dnscrypt-proxy2 +dnscrypt-proxy/dnscrypt-proxy2 +dnscrypt-proxy/dnscrypt-proxy + diff --git a/dnscrypt-proxy/config.go b/dnscrypt-proxy/config.go new file mode 100644 index 00000000..b79ea59d --- /dev/null +++ b/dnscrypt-proxy/config.go @@ -0,0 +1,83 @@ +package main + +import ( + "errors" + "fmt" + "log" + "time" + + "github.com/BurntSushi/toml" +) + +type Config struct { + ServerNames []string `toml:"server_names"` + ListenAddresses []string `toml:"listen_addresses"` + Daemonize bool + ForceTCP bool `toml:"force_tcp"` + Timeout int `toml:"timeout_ms"` + CertRefreshDelay int `toml:"cert_refresh_delay"` + ServersConfig map[string]ServerConfig `toml:"servers"` +} + +func newConfig() Config { + return Config{ + ListenAddresses: []string{"127.0.0.1:53"}, + Timeout: 2500, + CertRefreshDelay: 30, + } +} + +type ServerConfig struct { + Stamp string + ProviderName string `toml:"provider_name"` + Address string + PublicKey string `toml:"public_key"` + NoLog bool `toml:"no_log"` + DNSSEC bool `toml:"dnssec"` +} + +func ConfigLoad(proxy *Proxy, config_file string) error { + config := newConfig() + if _, err := toml.DecodeFile(config_file, &config); err != nil { + log.Println(err) + return err + } + proxy.timeout = time.Duration(config.Timeout) * time.Millisecond + proxy.mainProto = "udp" + if config.ForceTCP { + proxy.mainProto = "tcp" + } + proxy.certRefreshDelay = time.Duration(config.CertRefreshDelay) * time.Minute + if len(config.ListenAddresses) == 0 { + return errors.New("No local IP/port configured") + } + proxy.listenAddresses = config.ListenAddresses + proxy.daemonize = config.Daemonize + if len(config.ServerNames) == 0 { + for serverName := range config.ServersConfig { + config.ServerNames = append(config.ServerNames, serverName) + } + } + if len(config.ServerNames) == 0 { + return errors.New("No servers configured") + } + for _, serverName := range config.ServerNames { + serverConfig, ok := config.ServersConfig[serverName] + if !ok { + return fmt.Errorf("No definitions found for server [%v]", serverName) + } + var stamp ServerStamp + var err error + if len(serverConfig.Stamp) > 0 { + panic("Stamps are not implemented yet") + } else { + stamp, err = NewServerStampFromLegacy(serverConfig.Address, serverConfig.PublicKey, serverConfig.ProviderName) + if err != nil { + return err + } + } + proxy.registeredServers = append(proxy.registeredServers, + RegisteredServer{name: serverName, stamp: stamp}) + } + return nil +} diff --git a/dnscrypt-proxy/dnscrypt-proxy.toml b/dnscrypt-proxy/dnscrypt-proxy.toml new file mode 100644 index 00000000..4edd62dc --- /dev/null +++ b/dnscrypt-proxy/dnscrypt-proxy.toml @@ -0,0 +1,27 @@ +# dnscrypt-proxy configuration + +# List of servers to use +# If this line is commented, all registered servers will be used +server_names = ["dnscrypt.org-fr"] + +# List of local addresses and ports to listen to. Can be IPv4 and/or IPv6. +listen_addresses = ["127.0.0.1:53", "[::1]:53"] + +# Run the server as a background process +daemonize = false + +# Always use TCP to connect to upstream servers +force_tcp = false + +# Timeout, in milliseconds +timeout = 2500 + +# Delay, in minutes, after which certificates are reloaded +cert_refresh_delay = 30 + +# Static list of available servers +[servers] + [servers."dnscrypt.org-fr"] + provider_name = "2.dnscrypt-cert.fr.dnscrypt.org" + address = "212.47.228.136:443" + public_key = "E801:B84E:A606:BFB0:BAC0:CE43:445B:B15E:BA64:B02F:A3C4:AA31:AE10:636A:0790:324D" diff --git a/dnscrypt-proxy/main.go b/dnscrypt-proxy/main.go index 63bd2c41..d0face00 100644 --- a/dnscrypt-proxy/main.go +++ b/dnscrypt-proxy/main.go @@ -16,39 +16,50 @@ type Proxy struct { questionSizeEstimator QuestionSizeEstimator serversInfo ServersInfo timeout time.Duration + certRefreshDelay time.Duration mainProto string + listenAddresses []string + daemonize bool + registeredServers []RegisteredServer } func main() { log.SetFlags(0) - stamp, _ := NewServerStampFromLegacy("212.47.228.136:443", "E801:B84E:A606:BFB0:BAC0:CE43:445B:B15E:BA64:B02F:A3C4:AA31:AE10:636A:0790:324D", "2.dnscrypt-cert.fr.dnscrypt.org") - NewProxy("127.0.0.1:5399", "dnscrypt.org-fr", stamp, "udp") + proxy := Proxy{} + if err := ConfigLoad(&proxy, "dnscrypt-proxy.toml"); err != nil { + panic(err) + } + proxy.StartProxy() } -func NewProxy(listenAddrStr string, serverName string, stamp ServerStamp, mainProto string) { - proxy := Proxy{questionSizeEstimator: NewQuestionSizeEstimator(), timeout: TimeoutMax, mainProto: mainProto} +func (proxy *Proxy) StartProxy() { + proxy.questionSizeEstimator = NewQuestionSizeEstimator() if _, err := rand.Read(proxy.proxySecretKey[:]); err != nil { log.Fatal(err) } curve25519.ScalarBaseMult(&proxy.proxyPublicKey, &proxy.proxySecretKey) - proxy.serversInfo.registerServer(&proxy, serverName, stamp) - listenUDPAddr, err := net.ResolveUDPAddr("udp", listenAddrStr) - if err != nil { - log.Fatal(err) + for _, registeredServer := range proxy.registeredServers { + proxy.serversInfo.registerServer(proxy, registeredServer.name, registeredServer.stamp) } - listenTCPAddr, err := net.ResolveTCPAddr("tcp", listenAddrStr) - if err != nil { - log.Fatal(err) + for _, listenAddrStr := range proxy.listenAddresses { + listenUDPAddr, err := net.ResolveUDPAddr("udp", listenAddrStr) + if err != nil { + log.Fatal(err) + } + listenTCPAddr, err := net.ResolveTCPAddr("tcp", listenAddrStr) + if err != nil { + log.Fatal(err) + } + if err := proxy.udpListener(listenUDPAddr); err != nil { + log.Fatal(err) + } + if err := proxy.tcpListener(listenTCPAddr); err != nil { + log.Fatal(err) + } } - go func() { - proxy.udpListener(listenUDPAddr) - }() - go func() { - proxy.tcpListener(listenTCPAddr) - }() for { time.Sleep(CertRefreshDelay) - proxy.serversInfo.refresh(&proxy) + proxy.serversInfo.refresh(proxy) } } @@ -57,19 +68,22 @@ func (proxy *Proxy) udpListener(listenAddr *net.UDPAddr) error { if err != nil { return err } - defer clientPc.Close() - fmt.Printf("Now listening to %v [UDP]\n", listenAddr) - for { - buffer := make([]byte, MaxDNSPacketSize-1) - length, clientAddr, err := clientPc.ReadFrom(buffer) - if err != nil { - return err + go func() { + defer clientPc.Close() + fmt.Printf("Now listening to %v [UDP]\n", listenAddr) + for { + buffer := make([]byte, MaxDNSPacketSize-1) + length, clientAddr, err := clientPc.ReadFrom(buffer) + if err != nil { + return + } + packet := buffer[:length] + go func() { + proxy.processIncomingQuery(proxy.serversInfo.getOne(), proxy.mainProto, packet, &clientAddr, clientPc) + }() } - packet := buffer[:length] - go func() { - proxy.processIncomingQuery(proxy.serversInfo.getOne(), proxy.mainProto, packet, &clientAddr, clientPc) - }() - } + }() + return nil } func (proxy *Proxy) tcpListener(listenAddr *net.TCPAddr) error { @@ -77,23 +91,26 @@ func (proxy *Proxy) tcpListener(listenAddr *net.TCPAddr) error { if err != nil { return err } - defer acceptPc.Close() - fmt.Printf("Now listening to %v [TCP]\n", listenAddr) - for { - clientPc, err := acceptPc.Accept() - if err != nil { - continue - } - go func() { - defer clientPc.Close() - clientPc.SetDeadline(time.Now().Add(proxy.timeout)) - packet, err := ReadPrefixed(clientPc.(*net.TCPConn)) - if err != nil || len(packet) < MinDNSPacketSize { - return + go func() { + defer acceptPc.Close() + fmt.Printf("Now listening to %v [TCP]\n", listenAddr) + for { + clientPc, err := acceptPc.Accept() + if err != nil { + continue } - proxy.processIncomingQuery(proxy.serversInfo.getOne(), "tcp", packet, nil, clientPc) - }() - } + go func() { + defer clientPc.Close() + clientPc.SetDeadline(time.Now().Add(proxy.timeout)) + packet, err := ReadPrefixed(clientPc.(*net.TCPConn)) + if err != nil || len(packet) < MinDNSPacketSize { + return + } + proxy.processIncomingQuery(proxy.serversInfo.getOne(), "tcp", packet, nil, clientPc) + }() + } + }() + return nil } func (proxy *Proxy) exchangeWithUDPServer(serverInfo *ServerInfo, encryptedQuery []byte, clientNonce []byte) ([]byte, error) {