#go #ssl #post #x509certificate
#Вперед #ssl #Публикация #x509certificate
Вопрос:
С помощью следующего кода я создаю сертификат TLS
func loadCert() tls.Certificate {
b, err := ioutil.ReadFile(fileName)
if err != nil {
log.Fatalln("failed to find / open cert file", err)
}
p, c, err1 := pkcs12.Decode(b, password)
if err1 != nil {
log.Fatalln("Failed to read cert content", err1)
}
tlsCert := tls.Certificate{
PrivateKey: p,
Leaf: c,
}
return tlsCert
}
А затем с помощью NewCertPool() я добавляю это в пул
func makeRequest(){
// Loading cert
cert := loadCert()
caCertPool := x509.NewCertPool()
caCertPool.AddCert(cert.Leaf)
tConfig := amp;tls.Config{
RootCAs: caCertPool,
PreferServerCipherSuites: true,
InsecureSkipVerify: false,
Certificates: []tls.Certificate{cert},
}
tr := amp;http.Transport{
TLSClientConfig: tConfig,
}
client := http.Client{
Transport: tr,
}
request, reqError := http.NewRequest("POST", url, bytes.NewBuffer(dataToPost))
if reqError != nil {
log.Fatalln(" failed with error", reqError)
}
request.Header.Set("Accept", "*/*")
request.Header.Set("Connection", "keep-alive")
request.Header.Add("Content-Type", "text/xml;charset=UTF-8")
res, dErr := client.Do(request)
if dErr != nil {
log.Fatalln("Failed to make request", dErr)
} else {
log.Println(res.StatusCode)
}
}
SupportCertificate выдает
нет взаимно поддерживаемых версий протоколов
Тот же сертификат отлично работает с такими инструментами, как Postman. Если я удалю проверку с помощью этой функции supportCertificate и попытаюсь выполнить POST-вызов, сервер сообщает, что сертификат клиента не найден, несмотря на добавление его в транспорт выше. И на стороне клиента я получаю сообщение об ошибке, что соединение было сброшено и
x509: сертификат, подписанный неизвестным органом
Чтобы исправить это, я попытался использовать SystemCertPool() , после чего код не выполняется в Windows с ошибкой SystemCertPool не найден. В Docker или на виртуальной машине происходит сбой с
соединение было сброшено одноранговым узлом
Я действительно в недоумении, чего мне не хватает, был бы признателен за помощь в этом.
Я уже просмотрел действительно полезные сообщения о том, как можно настроить TLS и как сертификаты CA могут быть добавлены в новый пул. Но я все еще, кажется, что-то упускаю.
Комментарии:
1.
ClientHelloInfo.SupportsCertificate
необходимо вызвать воClientHelloInfo
время или после подтверждения связи TLS. Вы вызываете его для неинициализированного объекта. Удалите это и покажите часть кода, которая выполняет фактическую публикацию. Для пула CA пул системных сертификатов не работает в Windows, но есть обходной путь (вам нужно будет их найти)2. Вы также не должны добавлять свой собственный сертификат клиента в пул, вам нужен центр сертификации, который может проверять сертификат сервера (либо в системном пуле, либо в пользовательском, который вы укажете). Вам также не нужно устанавливать
ClientAuth
, это настройка на стороне сервера.3. @Marc я отредактировал свой вопрос с помощью кода для запроса POST. Как вы упомянули, я удалил ClientHello и cert из пула. Я могу смириться с тем, что это не работает в Windows, это не моя основная платформа. Итак, я переключил его на SystemCertPool и повторно выполнил его на виртуальной машине (Ubuntu 18). выдает> чтение tcp <localIP>:порт -> <serverIP>:<порт>: чтение: сброс соединения одноранговым узлом
4. Что говорит серверная сторона?
5. @Marc у меня нет доступа к серверу, это сервер внешнего провайдера. 🙁
Ответ №1:
Вы можете попробовать использовать свой http.Client
с настроенным tls.Config
, где вы переопределили корневой центр сертификации. Например:
http.Client{
Transport: amp;http.Transport{
TLSClientConfig: amp;tls.Config{
RootCAs: caPool,
},
},
где caPool
можно получить как
caPool, err := x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("SystemCertPool() error: %v", err)
}
if caPool == nil {
caPool = x509.NewCertPool()
}
certs, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read CA from file '%q': %v", path, err)
}
if ok := caPool.AppendCertsFromPEM(certs); !ok {
return nil, fmt.Errorf("failed to append local CA to root cert pool")
}
Комментарии:
1. Спасибо. Но это выглядит почти так же, как то, что я делаю. Единственное различие, которое я вижу, заключается в том, что вы проверяете, является ли SystemCertPool нулевым или нет. Очевидно, что это не работает в Windows, но мои тесты на docker (alpine image) и ubuntu 18 VM не возвращают нулевой системный пул.