Merge: + DNS, Web: Entware: use special directory with the system root certificates

Close #1311

* commit '0e030154ee4f73d0c1a8e9d092b12be78b0a0ea5':
  - fix tests
  + DNS, Web: Entware: use special directory with the system root certificates
This commit is contained in:
Simon Zolin 2020-03-17 14:18:02 +03:00
commit 5f328d20ca
6 changed files with 69 additions and 10 deletions

View File

@ -180,6 +180,8 @@ type ServerConfig struct {
FilteringConfig FilteringConfig
TLSConfig TLSConfig
TLSv12Roots *x509.CertPool // list of root CAs for TLSv1.2
// Called when the configuration is changed by HTTP request // Called when the configuration is changed by HTTP request
ConfigModified func() ConfigModified func()
@ -338,6 +340,7 @@ func (s *Server) Prepare(config *ServerConfig) error {
MinVersion: tls.VersionTLS12, MinVersion: tls.VersionTLS12,
} }
} }
upstream.RootCAs = s.conf.TLSv12Roots
if len(proxyConfig.Upstreams) == 0 { if len(proxyConfig.Upstreams) == 0 {
log.Fatal("len(proxyConfig.Upstreams) == 0") log.Fatal("len(proxyConfig.Upstreams) == 0")

View File

@ -200,6 +200,7 @@ func verifyCertChain(data *tlsConfigStatus, certChain string, serverName string)
opts := x509.VerifyOptions{ opts := x509.VerifyOptions{
DNSName: serverName, DNSName: serverName,
Roots: Context.tlsRoots,
} }
log.Printf("number of certs - %d", len(parsedCerts)) log.Printf("number of certs - %d", len(parsedCerts))

View File

@ -175,6 +175,7 @@ func generateServerConfig() dnsforward.ServerConfig {
newconfig.TLSListenAddr = &net.TCPAddr{IP: net.ParseIP(config.DNS.BindHost), Port: config.TLS.PortDNSOverTLS} newconfig.TLSListenAddr = &net.TCPAddr{IP: net.ParseIP(config.DNS.BindHost), Port: config.TLS.PortDNSOverTLS}
} }
} }
newconfig.TLSv12Roots = Context.tlsRoots
newconfig.FilterHandler = applyAdditionalFiltering newconfig.FilterHandler = applyAdditionalFiltering
newconfig.GetUpstreamsByClient = getUpstreamsByClient newconfig.GetUpstreamsByClient = getUpstreamsByClient

View File

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"context" "context"
"crypto/tls" "crypto/tls"
"crypto/x509"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -78,6 +79,7 @@ type homeContext struct {
pidFileName string // PID file name. Empty if no PID file was created. pidFileName string // PID file name. Empty if no PID file was created.
disableUpdate bool // If set, don't check for updates disableUpdate bool // If set, don't check for updates
controlLock sync.Mutex controlLock sync.Mutex
tlsRoots *x509.CertPool // list of root CAs for TLSv1.2
transport *http.Transport transport *http.Transport
client *http.Client client *http.Client
appSignalChannel chan os.Signal // Channel for receiving OS signals by the console app appSignalChannel chan os.Signal // Channel for receiving OS signals by the console app
@ -135,16 +137,6 @@ func run(args options) {
Context.configFilename = "AdGuardHome.yaml" Context.configFilename = "AdGuardHome.yaml"
} }
// Init some of the Context fields right away
Context.transport = &http.Transport{
DialContext: customDialContext,
Proxy: getHTTPProxy,
}
Context.client = &http.Client{
Timeout: time.Minute * 5,
Transport: Context.transport,
}
// configure working dir and config path // configure working dir and config path
initWorkingDir(args) initWorkingDir(args)
@ -172,6 +164,19 @@ func run(args options) {
initConfig() initConfig()
initServices() initServices()
Context.tlsRoots = util.LoadSystemRootCAs()
Context.transport = &http.Transport{
DialContext: customDialContext,
Proxy: getHTTPProxy,
TLSClientConfig: &tls.Config{
RootCAs: Context.tlsRoots,
},
}
Context.client = &http.Client{
Timeout: time.Minute * 5,
Transport: Context.transport,
}
if !Context.firstRun { if !Context.firstRun {
// Do the upgrade if necessary // Do the upgrade if necessary
err := upgradeConfig() err := upgradeConfig()
@ -321,6 +326,7 @@ func httpServerLoop() {
TLSConfig: &tls.Config{ TLSConfig: &tls.Config{
Certificates: []tls.Certificate{cert}, Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12, MinVersion: tls.VersionTLS12,
RootCAs: Context.tlsRoots,
}, },
} }

View File

@ -112,6 +112,7 @@ func TestHome(t *testing.T) {
dir := prepareTestDir() dir := prepareTestDir()
defer func() { _ = os.RemoveAll(dir) }() defer func() { _ = os.RemoveAll(dir) }()
_ = os.MkdirAll(filepath.Join(Context.getDataDir(), filterDir), 0755)
fn := filepath.Join(dir, "AdGuardHome.yaml") fn := filepath.Join(dir, "AdGuardHome.yaml")
assert.True(t, ioutil.WriteFile(fn, []byte(yamlConf), 0644) == nil) assert.True(t, ioutil.WriteFile(fn, []byte(yamlConf), 0644) == nil)

47
util/tls.go Normal file
View File

@ -0,0 +1,47 @@
package util
import (
"crypto/x509"
"io/ioutil"
"os"
"runtime"
"github.com/AdguardTeam/golibs/log"
)
// LoadSystemRootCAs - load root CAs from the system
// Return the x509 certificate pool object
// Return nil if nothing has been found.
// This means that Go.crypto will use its default algorithm to find system root CA list.
// https://github.com/AdguardTeam/AdGuardHome/issues/1311
func LoadSystemRootCAs() *x509.CertPool {
if runtime.GOOS != "linux" {
return nil
}
// Directories with the system root certificates, that aren't supported by Go.crypto
dirs := []string{
"/opt/etc/ssl/certs", // Entware
}
roots := x509.NewCertPool()
for _, dir := range dirs {
fis, err := ioutil.ReadDir(dir)
if err != nil {
if !os.IsNotExist(err) {
log.Error("Opening directory: %s: %s", dir, err)
}
continue
}
rootsAdded := false
for _, fi := range fis {
data, err := ioutil.ReadFile(dir + "/" + fi.Name())
if err == nil && roots.AppendCertsFromPEM(data) {
rootsAdded = true
}
}
if rootsAdded {
return roots
}
}
return nil
}