How To Secure HAProxy with Let's Encrypt on Ubuntu 14.04

HAProxy에서 Let's Encrypt를 적용하기 위하여 study 목적으로 번역한 내용이여서 검증되지 않는 내용을 포함할 수도 있습니다. 계속 내용을 수정할 예정입니다.

원문 : https://www.digitalocean.com/community/tutorials/how-to-secure-haproxy-with-let-s-encrypt-on-ubuntu-14-04

Let's Encrypt는 무료 TLS / SSL 인증서를 쉽게 얻고 설치할 수있는 새로운 인증 기관 (CA)이므로 웹 서버에서 암호화 된 HTTPS를 사용할 수 있습니다. 필요한 단계를 대부분 자동화하는 시도인 소프트웨어 클라이언트, letsencrypt를 제공함으로써 프로세스를 단순화합니다. 현재 Let's Encrypt는 공개 베타 버전이므로 인증서를 얻고 설치하는 전체 과정은 Apache 웹서버에서만 완전히 자동화됩니다. 그러나 Let's Encrypt를 사용하면 무료 SSL 인증서를 쉽게 얻을 수 있습니다. 이 인증서는 웹서버 소프트웨어 선택에 관계없이 수동으로 설치할 수 있습니다.

이 튜토리얼에서는 Let's Encrypt를 사용하여 무료 SSL 인증서를 얻고 Ubuntu 14.04에서 HAProxy와 함께 사용하는 방법을 보여줍니다. 또한 SSL 인증서를 자동으로 갱신하는 방법을 알려드립니다.

imgae

이 자습서를 수행하기 전에 몇 가지가 필요합니다.

Ubuntu 14.04 서버에 sudo 권한이 있는 root가 아닌 사용자 계정이 있어야 합니다. Ubuntu 14.04의 초기 서버 설정에서 1-3 단계를 수행하여 이러한 사용자 계정을 설정하는 방법을 배울 수 있습니다. initial server setup for Ubuntu 14.04

인증서를 사용할 등록된 domain name을 소유하거나 제어해야 합니다. 등록된 domain name이 없다면 많은 domain name 등록 기관 중 하나 (예 : Namecheap, GoDaddy 등)에 등록할 수 있습니다.

아직 도메인을 서버의 public IP 주소로 가리키는 A 레코드를 작성하지 않았는지 확인하세요. 이것은 Let's Encrypt가 인증서를 발급하는 도메인을 소유하고 있는지 확인하는 방법때문에 필요합니다. 예를 들어, example.com에 대한 인증서를 얻기위한 유효성 검사 프로세스가 작동하려면 해당 도메인이 서버로 확인되어야 합니다. 우리의 설치 프로그램은 example.com과 www.example.com을 도메인 이름으로 사용하므로 DNS 기록이 모두 필요합니다.

모든 필수 구성 요소를 준비했으면 Let's Encrypt 클라이언트 소프트웨어 설치로 넘어 갑니다.

1단계 — Let's Encrypt Client 설치

Let's Encrypt를 사용하여 SSL 인증서를 얻는 첫 번째 단계는 서버에 letsencrypt 소프트웨어를 설치하는 것입니다. 현재, Let's Encrypt를 설치하는 가장 좋은 방법은 공식 GitHub 저장소에서 단순히 복제하는 것입니다. 앞으로는 패키지 관리자를 통해 제공 될 것입니다.

Git과 bc 설치

이제 Git과 bc를 설치하여 Let's Encrypt 저장소를 복제 할 수 있습니다. 아래 명령으로 서버의 패키지 관리자를 업데이트하십시오.

$ sudo apt-get update

그런 다음 apt-get을 사용하여 git 및 bc 패키지를 설치하십시오

$ sudo apt-get -y install git bc

git와 bc를 설치하면 GitHub에서 저장소를 복제하여 쉽게 letsencrypt를 다운로드할 수 있습니다.

Clone Let's Encrypt

이제 다음 명령으로 /optLet's Encrypt 저장소를 복제할 수 있습니다.

$ sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

이제 /opt/letsencrypt 디렉토리에 letsencrypt 저장소 사본이 있어야 합니다.

2단계 - 인증서 얻기

Let's Encrypt는 다양한 플러그인을 통해 SSL 인증서를 얻는 다양한 방법을 제공합니다. 다른 튜토리얼에서 다루는 아파치 플러그인과는 달리, 대부분의 플러그인은 웹서버를 수동으로 구성해야하는 인증서를 얻는데 도움이 됩니다. 인증서를 가져오고 설치하지 않는 플러그인은 서버에 인증서를 발급해야하는지 여부를 인증하는데 사용되므로 "인증 자"라고 합니다.

SSL 인증서를 얻기 위해 Standalone plugin을 사용하는 방법을 알려 드리겠습니다.

80번 포트가 열려있는 지 확인

Standalone plugin은 SSL 인증서를 얻을 수있는 매우 간단한 방법을 제공합니다. 서버에서 80번 포트의 작은 웹서버를 임시로 실행하면 인증서를 발급하기 전에 암호화 CA가 서버 ID에 연결하여 유효성을 검사할 수 있습니다. 따라서 이 방법을 사용하려면 80번 포트를 사용하고 있지 않아야 합니다. 즉, 이 플러그인을 사용하기 전에 80번 포트(예: http)을 사용하는 일반 웹서버를 중지하십시오.

예를 들어 HAProxy를 사용하는 경우 다음 명령을 실행하여 HAProxy를 중지할 수 있습니다.

$ sudo service haproxy stop

80번 포트이 사용 중인지 확실하지 않을 경우 다음 명령을 실행할 수 있습니다.

netstat -na | grep ':80.*LISTEN'  

이 명령을 실행했을 때 출력이 없으면 Standalone plugin을 사용할 수 있습니다.

Let's Encrypt 실행

Let's Encrypt를 사용하기 전에 letsencrypt 디렉토리로 변경하세요.

$ cd /opt/letsencrypt

이제 다음 명령을 실행하여 Standalone plugin을 사용하세요.

$ ./letsencrypt-auto certonly --standalone

Let's Encrypt 소프트웨어는 수퍼 유저 권한이 필요하므로 최근에 sudo를 사용하지 않았다면 암호를 입력해야합니다.

letsencrypt가 초기화된 후 몇 가지 정보를 묻는 메시지가 나타납니다. 이전에 Let's Encrypt를 사용했는지 여부에 따라 달라질 수 있지만 처음부터 다시 시작하겠습니다.

프롬프트에서 알림 및 손실된 키 복구에 사용될 전자 메일 주소를 입력하십시오.

image

그러면 Let's Encrypt Subscribe 계약에 동의해야합니다. 동의(Agree)을 선택하십시오. image

그런 다음 도메인 이름을 입력하십시오. 단일 인증서를 여러 도메인 이름 (예: example.com 및 www.example.com)과 함께 사용하려면 모든 인증서를 포함해야합니다. image

모든 것이 성공하면 다음과 같은 출력 메시지가 나타납니다.

Output:  
IMPORTANT NOTES:  
 - If you lose your account credentials, you can recover through
   e-mails sent to sammy@digitalocean.com
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your
   cert will expire on 2016-03-15. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - Your account credentials have been saved in your Let's Encrypt
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Let's
   Encrypt so making regular backups of this folder is ideal.
 - If like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

예제 출력에서 강조 표시된 인증서의 경로와 만기 날짜를 기록해 두는 것이 좋습니다.

도메인이 CloudFlare와 같은 DNS 서비스를 통해 라우팅하는 경우 인증서를 얻을 때까지 일시적으로 비활성화해야합니다.

인증서 파일

인증서를받은 후 다음과 같은 PEM 인코딩 파일을 갖게 됩니다.

  • cert.pem : 도메인 인증서
  • chain.pem : Let's Encrypt 체인 인증서
  • fullchain.pem : cert.pem 및 chain.pem 결합
  • privkey.pem : 인증서의 private key

방금 작성한 인증서 파일의 위치를 알고 있으므로 웹 서버 구성에서 사용할 수 있습니다. 파일 자체는 /etc/letsencrypt/archive의 서브 디렉토리에 있습니다. 그러나 Let's Encrypt/etc/letsencrypt/live/your_domain_name 디렉토리의 가장 최근 인증서 파일에 대한 심볼릭 링크를 만듭니다.

다음 명령을 실행하여 파일이 존재하는지 확인할 수 있습니다 (도메인 이름으로 대체):

$ sudo ls /etc/letsencrypt/live/your_domain_name

출력은 위에서 언급 한 네 개의 인증서 파일이어야 합니다.

Fullchain.pem과 Privkey.pem을 결합

SSL 종료를 수행하도록 HAProxy를 구성할 때 자체와 최종 사용자간의 트래픽을 암호화하므로 fullchain.pem과 privkey.pem을 단일 파일로 결합해야 합니다.

먼저, 결합된 파일을 저장할 디렉토리 /etc/haproxy/certs를 만듭니다.

$ sudo mkdir -p /etc/haproxy/certs

다음으로, 이 cat 명령으로 결합된 파일을 만듭니다. (강조 표시된 example.com을 domain name으로 대체하십시오).

$ DOMAIN='example.com' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt

다음 명령을 사용하여 private key가 들어있는 결합된 파일에 안전하게 액세스하십시오.

$ sudo chmod -R go-rwx /etc/haproxy/certs

이제 우리는 SSL 인증서와 개인 키를 HAProxy와 함께 사용할 준비가 되었습니다.

3단계 - HAProxy 설치

이 단계는 HAProxy의 설치를 포함합니다. 서버에 이미 설치되어있는 경우, 이 단계를 건너 뜁니다.

우리는 기본 우분투 저장소에 없는 HAProxy 1.6을 설치합니다. 그러나 PPA를 사용하는 경우 다음 명령을 사용하여 패키지 관리자를 사용하여 HAProxy 1.6을 설치할 수 있습니다.

$ sudo add-apt-repository ppa:vbernat/haproxy-1.6

로드 밸런서에서 로컬 패키지 색인을 업데이트하고 다음을 입력하여 HAProxy를 설치하십시오.

$ sudo apt-get update
$ sudo apt-get install haproxy

HAProxy가 설치되었지만 구성해야합니다.

단계 4 - HAProxy 설정

이 섹션에서는 SSL 설정으로 기본 HAProxy를 구성하는 방법을 보여줍니다. 또한 Let's Encrypt 인증서를 자동 갱신할 수 있도록 HAProxy를 구성하는 방법을 설명합니다.

텍스트 편집기에서 haproxy.cfg을 편집합니다.

$ sudo nano /etc/haproxy/haproxy.cfg

이 파일은 다음 몇 섹션에서 편집 할 때 열어 두세요.

Global Section

Global Section 아래에 몇 가지 기본 설정을 추가해 보겠습니다.

가장 먼저해야 할 일은 maxconn을 적당한 수로 설정하는 것입니다.
이는 HAProxy가 허용하는 동시 연결 수에 영향을 주지만,이는 QoS에 영향을 미치고 웹 서버가 너무 많은 요청을 처리하지 못하는 것을 막을 수 있습니다. 귀하의 환경에 적합한 것을 찾으려면 play around가 필요합니다. 합리적인 값을 가진 다음 줄을 Global Section 추가하십시오.

   maxconn 2048

그런 다음 이 줄을 추가하여 생성되는 임시 DHE 키의 최대 크기를 구성하십시오.

   tune.ssl.default-dh-param 2048
Defaults Section

defaults 섹션에 다음 행을 추가하십시오.

   option forwardfor
   option http-server-close

forwardfor 옵션은 HAProxy가 각 요청에 X-Forwarded-For 헤더를 추가하도록 설정하고 http-server-close 옵션은 연결을 닫지만 keep-alives를 유지함으로써 HAProxy와 사용자 간의 대기 시간을 줄입니다.

Frontend Sections

이제 Frontend Sections을 정의할 준비가 되었습니다.
추가하고자하는 첫 번째 작업은 들어오는 HTTP 연결을 처리하고 기본 백엔드로 전송하는 프론트 엔드입니다 (나중에 정의 할 것입니다). 파일의 끝에서 www-http라는 프론트 엔드를 추가합시다. haproxy_public_IP를 HAProxy 서버의 공용 IP 주소로 바꾸십시오.

frontend www-http  
   bind haproxy_www_public_IP:80
   reqadd X-Forwarded-Proto:\ http
   default_backend www-backend

다음으로 프론트 엔드를 추가하여 들어오는 HTTPS 연결을 처리합니다. 파일의 끝에 www-https라는 프론트 엔드를 추가하십시오. haproxy_www_public_IP를 HAProxy 서버의 공인 IP로 바꾸십시오. 또한 example.com을 도메인 이름 (이전에 생성 한 인증서 파일과 일치해야 함)으로 바꿔야합니다.

frontend www-https  
   bind haproxy_www_public_IP:443 ssl crt /etc/haproxy/certs/example.com.pem
   reqadd X-Forwarded-Proto:\ https
   acl letsencrypt-acl path_beg /.well-known/acme-challenge/
   use_backend letsencrypt-backend if letsencrypt-acl
   default_backend www-backend

이 프론트 엔드는 ACL(letsencrypt-acl)을 사용하여 유효화 요청 (/.well-known/acme-challenge)을 letsencrypt-backend 백엔드에 보냅니다. 그러면 HAProxy 서비스를 중지하지 않고 인증서를 갱신할 수 있습니다. 다른 모든 요청은 웹 응용 프로그램이나 사이트를 제공 할 백엔드인 www-backend로 전달됩니다.

Backend Sections

프론트 엔드 구성을 완료 한 후, 다음 행을 추가하여 www-backend 백엔드를 추가하십시오. 강조 표시된 단어를 웹 서버의 개별 IP 주소로 바꾸십시오 (보유하고 있는 백엔드 서버 수와 일치하도록 서버 행 수 조정).

backend www-backend  
   redirect scheme https if !{ ssl_fc }
   server www-1 www_1_private_IP:80 check
   server www-2 www_2_private_IP:80 check

이 백엔드에서 수신하는 모든 트래픽은 HTTP(80번 포트)를 통해 서버 항목간에 균형을 유지합니다. 마지막으로, 다음 행을 추가하여 letsencrypt-backend 백엔드를 추가하십시오.

backend letsencrypt-backend  
   server letsencrypt 127.0.0.1:54321

이 백엔드는 인증서 요청 및 갱신에 사용되는 Let's Encrypt ACME 문제만 처리하여 54321 포트의 로컬 호스트에 트래픽을 전송합니다.
우리는 Let's Encrypt SSL 인증서를 갱신 할 때 80443대신 이 포트를 사용합니다. 이제 우리는 HAProxy를 시작할 준비가되었습니다:

$ sudo service haproxy restart

haproxy.cfg 구성 파일에 문제가있는 경우이 GitHub Gist에서 예제를 확인하십시오.

Let's Encrypt TLS/SSL 인증서가 설치되었으며 자동 갱신 스크립트를 설정할 준비가되었습니다. 이 시점에서 웹 브라우저에서 도메인을 방문하여 TLS/SSL 인증서가 작동하는지 테스트해야합니다.

5단계 - 자동 갱신 설정

Let's Encrypt Certificate는 90일동안 유효하지만 오류가 허용되도록 60 일마다 인증서를 갱신하는 것이 좋습니다. 이 글을 쓰는 시점에서 클라이언트의 기능으로 자동 갱신을 계속 사용할 수는 없지만 Let's Encrypt 클라이언트를 다시 실행하여 인증서를 수동으로 갱신할 수 있습니다.

인증서가 구형이 되지않도록 하는 실질적인 방법은 갱신 프로세스를 자동으로 처리하는 cron 작업을 만드는 것입니다. 앞에서 사용했던 대화형 메뉴 기반 프로세스를 피하기 위해 cron 작업에서 Let's Encrypt 클라이언트를 호출할 때 다른 매개 변수를 사용합니다.

앞에서 사용된 Standalone plugin을 사용하지만 포트 54321을 사용하도록 구성하여 HAProxy (포트 80443에서 수신 대기)와 충돌하지 않도록합니다. 이렇게 하려면 다음 명령을 사용합니다 (강조 표시된 example.com 도메인 둘 다 도메인 이름으로 대체).

$ cd /opt/letsencrypt
$ ./letsencrypt-auto certonly --agree-tos --renew-by-default --standalone-supported-challenges http-01 --http-01-port 54321 -d example.com -d www.example.com

성공하면 다음과 같이 결합된 인증서 파일을 새로 만들어야 합니다 (example.com을 도메인 이름으로 바꿉니다).

$ DOMAIN='example.com' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt/live/$DOMAIN/privkey.pem > /etc/haproxy/certs/$DOMAIN.pem'

그런 다음 HAProxy를 다시로드하여 새 인증서를 사용하십시오.

$ sudo service haproxy reload

이제 인증서를 갱신해야하는 명령을 알았으므로 스크립트와 cron 작업을 사용하여이 프로세스를 자동화할 수 있습니다.

Let's Encrypt 구성 파일 생성

계속하기 전에 /usr/local/etc/le-renew-haproxy.ini에 Let's Encrypt 구성 파일을 작성하여 갱신 프로세스를 간소화합시다.

$ sudo cp /opt/letsencrypt/examples/cli.ini /usr/local/etc/le-renew-haproxy.ini

이제 편집을 위해 파일을 엽니다.

sudo nano /usr/local/etc/le-renew-haproxy.ini  

그런 다음 전자 메일도메인 라인의 주석 처리를 제거하고 사용자 자신의 정보로 업데이트하십시오. 주석이 제거된 파일은 다음과 같이 보일 것입니다:

rsa-key-size = 4096

email = you@example.com

domains = example.com, www.example.com  

그런 다음 standalone-supported-challenges 라인의 주석 처리를 제거하고 해당 값을 http-01로 바꿉니다.

standalone-supported-challenges = http-01  

이제 명령에서 도메인 이름을 지정하는 대신 Let's Encrypt 구성 파일을 사용하여 공백을 채울 수 있습니다. 구성 파일이 올바른 것으로 가정하면 이 명령을 사용하여 인증서를 갱신할 수 있습니다.

cd /opt/letsencrypt  
./letsencrypt-auto certonly --renew-by-default --config /usr/local/etc/le-renew-haproxy.ini --http-01-port 54321

le-renew-haproxy.ini 구성 파일에 문제가있는 경우이 GitHub Gist에서 예제를 확인하십시오.
이제 인증서를 갱신하는 데 사용할 수있는 스크립트를 작성해 보겠습니다.

갱신 스크립트 만들기

갱신 프로세스를 자동화하기 위해 제공된 도메인의 인증서 만료 날짜를 확인하고 만료일이 30일보다 짧은 경우 갱신을 요청하는 쉘 스크립트를 사용합니다. 이 스크립트는 일주일에 한 번 실행되도록 예약됩니다. 이렇게 하면 cron작업이 실패하더라도 매주 다시 시도 할 수있는 30 일짜리 창이 있습니다.

먼저 스크립트를 다운로드하여 실행 가능하게 만드십시오. 스크립트를 다운로드하기 전에 스크립트의 내용을 자유롭게 검토하십시오.

$ sudo curl -L -o /usr/local/sbin/le-renew-haproxy https://gist.githubusercontent.com/thisismitch/7c91e9b2b63f837a0c4b/raw/700cfe953e5d5e71e528baf20337198195606630/le-renew-haproxy
$ sudo chmod +x /usr/local/sbin/le-renew-haproxy

le-renew-haproxy 스크립트는 갱신을 확인하려는 인증서의 domain name을 인수로 취합니다. 갱신이 아직 필요하지 않으면 주어진 인증서 만료일까지 남은 일수를 출력합니다.

/usr/local/etc/le-renew-haproxy.ini 파일이 없으면 스크립트가 실행되지 않습니다. 또한 구성 파일에 지정된 첫 번째 도메인이 원래 인증서를 만들 때 지정한 첫 번째 도메인과 동일해야합니다.

지금 스크립트를 실행하면이 인증서가 만료되는 데 남은 일수를 볼 수 있습니다.

$ sudo le-renew-haproxy
output  
Checking expiration date for example.com...  
The certificate is up to date, no need for renewal (89 days left).  

다음으로, 매주 이 명령을 실행할 새로운 작업을 작성하기 위해 crontab을 편집합니다. 루트 사용자의 crontab을 편집하려면 다음을 실행하십시오.

$ sudo crontab -e

다음 내용을 모두 한 줄에 포함하십시오.

30 2 * * 1 /usr/local/sbin/le-renew-haproxy >> /var/log/le-renewal.log  

저장 및 종료합니다. 매주 월요일 오전 2시30분에 le-renew-haproxy 명령을 실행할 새 크론 작업이 생성됩니다. 명령에 의해 생성된 출력은 /var/log/le-renewal.log에 있는 로그 파일로 저장됩니다.

결론

HAProxy는 이제 TLS / SSL 암호화 인증서를 사용하여 HTTPS 트래픽을 안전하게 제공합니다.

Martin

Read more posts by this author.