HTTPs-сервер с сертификатом Let’s Encrypt на Go

от автора

У меня есть приложение на Go, в котором в одном из потоков работает простой HTTP сервер. К этому серверу обращаются по HTTPS. Запрос приходит на Pound — HTTP/HTTPS reverse-proxy and load-balancer и перенаправляется в приложение. TLS сертификат изготавливается и обновляется с помощью Let’s Encrypt.

Простая и привычная схема. Правда, чаще в этой схеме бывает Nginx, но в этой статье мы не будем рассуждать, почему Pound, а не Nginx. Все очень хорошо, но меня последнее время начинает раздражать, когда к простому и понятному коду на Go нужно прикрутить небольшого динозаврика с пять-шестью скриптами на Ansible, закатать все это в деплой и радоваться тому, как это все славно улеглось в небольшой виртуалке.

HTTP на Go + Pound или Nginx + TLS with Let's Encrypt
HTTP на Go + Pound или Nginx + TLS with Let’s Encrypt

Я где-то там, в своем начале длительное время писал на Assembler-е. Размер откомпилированной программы больше одного Кб считался огромным. Видимо с тех пор во мне застряло желание экономить ресурсы компьютера, несмотря на то, что разработчики железа предоставляют их все больше и больше. Так же я ни как не могу привыкнуть к этим жутким папкам под названием ‘node_modules’ и всегда хочу стереть их содержимое.

И я задумался…
Задумался над тем, как можно сократить количество участников в задаче «HTTP-сервер с сертификатом Let’s Encrypt на Go». Год думал. Шучу. Мое приложение с динозавриками замечательно проработало год, и настало время сделать обновления.

И решение нашлось. Оказывается, все, что нужно для облегчения этой задачи, есть в библиотеке Go. Итак, вот что нужно написать в программе на Go для того, что бы работал HTTPS сервер и автоматически создавался и обновлялся TLS сертификат по технологии Let’s Encrypt:

mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, TLS user! Your config: %+v", r.TLS) }) log.Fatal(http.Serve(autocert.NewListener(domain), mux))

И все! Да, и все — те же самые стандартные три строчки, которые присутствуют во всех примерах создания HTTP-сервера. Ищем отличия, а я посмотрю на секундомер…
Ну конечно! — ‘autocert.NewListener(domain)’ в ‘http.Serve’.

Приложение, использующее этот код, должно быть запущено с правами администратора, и на хосте должен быть белый IP адрес. Без него Let’s Encrypt не сможет создать сертификат.

Для того что бы работала привычная нам переадресация с HTTP на HTTPS, добавим еще пару строк кода перед предыдущим кодом:

go func() { if err := http.ListenAndServe(":80", http.HandlerFunc(redirectTLS)); err != nil { log.Fatalf("ListenAndServe error: %v", err) } }()

Здесь мы создали еще один HTTP сервер, работающий на 80-м порту и пересылающий все на наш основной сервер с помощью функции ‘redirectTLS’:

func redirectTLS(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "https://"+domain+":443"+r.RequestURI, http.StatusMovedPermanently) }

Приложение имеет параметр ‘–domain’ и строка запуска выглядит так:

sudo go run . -domain=example.com

Конечно. Для запуска этого приложения у вас должен быть зарегистрированный домен и белый IP адрес.

Программа размещена на Github:
https://github.com/kirill-scherba/https-example

Вот ещё один адрес на Gitflic, пока он запасной:
https://gitflic.ru/project/kirill-scherba/https-example


ссылка на оригинал статьи https://habr.com/ru/post/662940/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *