Go сервер Https
Пытаюсь запустить приложение, написанное на Go, с использованием самоподписанного SSL сертификата. Пример:
func main() {
mux := http.NewServeMux()
mux.Handle("/", httpHandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.Error(w, "404", http.StatusNotFound)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Hello Https"))
}))
http.Handle("/assets/", http.FileServer(http.Dir(".")))
log.Fatal(http.ListenAndServeTLS(":443", "cert.pem", "cert.key", mux))
}
Какие действия предпринимались:
- Создание сертификата через гошный generate_cert.go, но получаю ошибку: TLS handhsake EOF
- Пробовал с помощью встроенного в Linux openssl создать сертификат, результат тот же
Как генерирую сертификат: go run generate_cert.go --host="127.0.0.1" (в случае со встроенной утилитой) openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 (в случае со встроенным в linux openssl)
UPD: Браузер считает сертификат (Acme Co) не подлинным / ненадёжным
Ответы (2 шт):
Самоподписанные сертификаты в доверенные нужно добавить с помощью ca-certificates Тут вроде норм инструкция https://unix.stackexchange.com/questions/90450/adding-a-self-signed-certificate-to-the-trusted-list
Поскольку ответа я так и не получил и изначально сформулировал вопрос не совсем корректно, а задачу уже решил самостоятельно, отвечу для тех, кому это в дальнейшем может пригодится.
Есть два пути решения:
- Проксирование через Nginx
- Использование пакета autocert (https://pkg.go.dev/golang.org/x/crypto/acme/autocert)
Примечание:
Что в первом, что во-втором случае, вам необходимо обзавестись доменом (поскольку для IP адреса выпустить SSL сертификат не получится).
Первый вариант (с Nginx) универсальный (по этой и другим причинам я на нём и остановился), но, лучше всего подходит в том случае, когда ваш проект использует несколько сервисов (допустим, основной сайт у вас работает на Go, на 80 и 443 порту, а сервис оплаты на Java у вас работает на 8000 порту).
Второй вариант (autocert) будет оптимальным, если ваше приложение (веб-сервис) написан на Go и проксировать какие-то определенные маршруты на другое приложение, запущенное на другом порту, не нужно.
В первом варианте вам необходимо установить nginx, затем открыть 80 и 443 порты (напр. через ufw, если у вас ubuntu), после чего запустить вашу программу на Go на каком-нибудь условном 9000 порту, открыть sudo nano /etc/nginx/sites-available/default и сделать proxy_pass на ваше Go приложение с указанием порта (в нашем случае 9000). Перезапустить nginx с помощью systemctl restart nginx. Всё.
В первом случае (с Nginx), вам необходимо сделать следующее:
- Установить nginx
- Открыть порты (80 и 443). Для Ubuntu это делается через ufw
- Проверить, что ufw (как и nginx) включен и работает
- Установить certbot-nginx
- Привязать ваш домен к IP адресу вашего сервера (обычно у хостера в настройках просто меняете DNS записи и всё готово)
- Выпустить сертификат для домена с помощью команды: sudo certbot --nginx -d mysite.ru -d www.mysite.ru (если пишет ошибку, подождите пока обновятся данные DNS). Если прошло больше суток, а сертификат не выпускается, проверьте, что домен привязан к IP. См. пункт 5.
- Прописать proxy_pass на порт вашего приложения на Go с помощью: sudo nano /etc/nginx/sites-available/default
- Перезапустить Nginx с помощью: sudo systemctl restart nginx
- В методе ListenAndServerTLS указать путь к файлу key и cert (они обычно лежат по пути: /etc/letsencrypt). См. терминал.
- Запустить приложение на Go и протестировать
Во-втором случае (с autocert), если кто-нибудь пробовал, дополните. Но общий принцип: https://gist.github.com/alexedwards/fd7e2725962be79a00818488ea1bcd00
Надеюсь, это было полезно.