[SpringBoot] Https 적용하기 (Let's Encrypt)

livenow·2020년 11월 17일
0
post-thumbnail

안녕하세요,

iptime과 Raspberry with Ubuntu server 20.04.1 lts로 80포트에 서비스를 구동중인 상태에서 443포트로 변경하기 위해 찾아봤던 내용들을 정리하였습니다

서버의 상황

  • iptime의 도메인 서비스를 이용하여 ip주소가 아닌 도메인 주소로 웹페이지에 접근할 수 있습니다.
  • nginx를 쓰려했지만, 이미 iptime에서 포트포워딩을 진행하고 있고, 또한 letsencrypt가 더이상 iptime의 도메인을 지원하지 않아 인증서를 발급받기 힘들었습니다. (20.09 기준으로 지원하지 않는다 함)

이러한 연유로 저는 조금 다르게 (편법을 써서) 인증서 발급 진행을 했습니다.

첫 번째, SSL, HTTPS, CA의 개념

이부분은 잘 정리되어 있는 링크를 통해 남기겠습니다.

https://galid1.tistory.com/602

두 번째, Certbot 설치

apt-get에 certbot 저장소를 추가합니다.

$ sudo add-apt-repository ppa:certbot/certbot

패키지 목록을 업데이트하고 certbot을 설치합니다

$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx

세 번째, 인증서 발급받기

제가 쓸 인증 서비스는 Let's Encrypt라는 무료 인증서 서비스입니다.

Let's Encrypt는 다양한 plugin을 통해 SSL 인증서를 제공하는데 저희는 webroot plugin을 통해서 인증서를 발급하겠습니다.

Webroot Plugin 사용

/.well-known 이라는 폴더에 파일을 추가해서 Let's Encrypt 서버가 접속 할 수 있게합니다.

저는 우선 default.conf를 통해 설정했습니다.

#파일열기 
$ sudo vim /etc/nginx/sites-available/default
#파일내 location 부분 추가 후 저장
server {
        ...
        location ~ /.well-known {
                allow all;
        }
        ...
}
#nginx의 설정 파일 문법 확인 
$ sudo nginx -t
#nginx 재시작 
$ sudo service nginx restart

인증서를 발급하기 위해서는 이후 사용할 명령어의 webroot-path라는 부분에 nginx server block의 root 경로를 지정해줘야 발급이 가능합니다.

확인해봅니다.

#파일열기 
$ vim /etc/nginx/sites-available/default
#root 부분 파일 경로 확인 
server {
        ...
        root /usr/share/nginx/html;
        ....
}

인증서를 발급할 준비가 완료 됐습니다.

인증서 발급

-d 옵션 뒤에 인증서를 사용할 도메인을 넣어줍니다. -d 옵션을 추가하면서 도메인 추가 또한 가능합니다.

$ sudo certbot certonly --webroot --webroot-path=/usr/share/nginx/html -d example.com -d dev.example.com

저는 이렇게 넣었습니다.

$ sudo certbot certonly --webroot --webroot-path=/usr/share/nginx/html -d mydomain.org 

처음 적용이라면, 이메일 저장과 Terms of Service에 동의합니다. (인증서가 만료 되는 시점에 메일을 보내주는 것으로 알고있음)

밑의 부분은 Certbot으로 무료 인증서 발급 받기 에서 가져왔습니다.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): [사용할 이메일 주소 입력]
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org

-------------------------------------------------------------------------------
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v01.api.letsencrypt.org/directory
-------------------------------------------------------------------------------
(A)gree/(C)ancel: A 

-------------------------------------------------------------------------------
Would you be willing to share your email address with the Electronic Frontier

Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about EFF and
our work to encrypt the web, protect its users and defend digital rights.
-------------------------------------------------------------------------------
(Y)es/(N)o: Y

HTTPS로 전환하면서 Redirect를 허용할 것인지 안할 것 인지 결정합니다. 저는 nginx를 통해 80포트로 들어와도 443으로 변경할 수 있게 2번을 선택했습니다. (이번 포스팅에서는 다루지 않습니다)

밑의 부분은 How To Secure Nginx with Let's Encrypt on Ubuntu 20.04 에서 가져왔습니다.

Output
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

선택을 하고 Enter를 하면 성공적으로 완료 되었다는 정보와, 인증서와 키가 어디에 저장되었는지 알려줍니다.

Output
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2020-08-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

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

Certificate 파일 확인

webroot plugin을 통해 잘 발급을 받았다면 아래와 같은 4개의 파일들이 생성됩니다.

  • cert.pem: 도메인의 인증서 / 기본 공개키
  • chain.pem: Let’s Encrypt chain 인증서 / 기타 정보를 포함한 공개키(이것이 없으면 Firefox나 모바일 크롬에서 Https 미적용)
  • fullchain.pem: cert.pem + chain.pem
  • privkey.pem: 인증서의 개인키

위의 파일들은 /etc/letsencrypt/archive에 위치하며 /etc/letsencrypt/live/[domain_name]에서 가장 최근의 인증서들에 대해 symbolic link를 가지고 있습니다.

/etc/letsencrypt/live에서 가장 최신의 인증서를 가지고 있기 때문에 인증서와 키들을 참조할 때 /etc/letsencrypt/live/[domain_name] 폴더를 이용해야 합니다.

관리자 권한이 아니면 파일 접근이 불가능 하니 우선 관리자 권한으로 변경합니다.

$ sudo su

관리자 권한이후 접근이 가능한 것을 확인할 수 있습니다.

# ls -l /etc/letsencrypt/live/[domain_name]

디피-헬만 그릅 추가

ssl의 보안을 높이기 위해 디피-헬만 그룹을 추가합니다.

# sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
#파일 확인
# /etc/ssl/certs/

네 번째, 문제와 해결

처음 말했듯이, letsencrypt 인증서가 더이상 iptime 도메인에 적용을 시키지 못한다고 해서, 인증서 적용 자체가 안됐기 때문에 편법을 사용했습니다.

letsencrypt에 있는 인증서 파일들을 홈 디렉토리에 옮깁니다. (저는 home의 secure폴더를 임의로 생성해서 거기 안에 넣기로 하였습니다.)

또한 심볼릭 링크가 담겨있는 /etc/letsencrypt/live/[domain_name] 폴더가 아닌 /etc/letsencrypt/archive/[domain_name] 폴더의 인증서를 사용했습니다.

$ sudo su
# cp -r /etc/letsencrypt/archive/[domain_name] /home/secure

PKCS12로 변환하기

# cd /home/secure
# ls -l

파일명을 확인해서 제일 최근의 파일로 PKCS12 변환을 시도합니다.

저는 1번이 최근파일로 되어있었습니다.

# openssl pkcs12 -export -in cert1.pem -inkey privkey1.pem -out cert_and_key.p12 -name ttp -CAfile chain1.pem -caname root

위 명령어를 사용하면 사용할 암호를 입력하라는 문구가 뜹니다.

Enter Export Password:
Verifying - Enter Export Password:

적절하고, 기억할 번호로 설정합니다.

cert_and_key.p12 이 생성된 것을 확인할 수 있습니다.

Keytool을 통해 jks 파일 만들기

# keytool -importkeystore -deststorepass [사용할 암호] -destkeypass [사용할 암호] -destkeystore [생성할 jks 파일명] -srckeystore cert_and_key.p12 -srcstoretype PKCS12 -srcstorepass [PKCS12에서 사용한 암호 (위에서 입력한 암호)]

저는 아래와 같이 진행했습니다.

keytool -importkeystore -deststorepass mymy -destkeypass mymy -destkeystore letsencrypt.jks -srckeystore cert_and_key.p12 -srcstoretype PKCS12 -srcstorepass password

letsencrypt.jks 이 생성된 것을 확인할 수 있습니다.

Import하기

# keytool -import -trustcacerts -alias root -file chain1.pem -keystore letsencrypt.jks

위의 명령어를 입력하면 아래와 같이 입력부분이 뜹니다.

Enter keystore password: [openssl pkcs12 입력한 암호]
Certificate was added to keystore

pem 인증서를 jks 파일로 변환하고, 해당 변환된 파일을 keytool에 import까지 하였습니다.

이제 SpringBoot에서 사용할 인증서가 모두 준비되었습니다.

마지막, 프로젝트 yml 파일에 적용

구동하고 있는 SpringBoot 서버의 yml옵션에 아래와 같이 추가합니다.

server:
  port: [구동할 port]
  ssl:
    enable: true
    key-store: [생성한 jks파일위치 ex) /home/secure/letsencrypt.jks)]
    key-store-password: [jks를 만들때 입력한 암호]
    key-password: [jks를 만들때 입력한 암호]
spring:
			...

결론

90일간 사용할 수있는 인증서를 받는 과정을 살펴보았습니다.

iptime공유기를 통해 포트포워딩을 하니 다른분들의 래퍼런스와 맞지 않아 힘들었습니다.

인증서가 7일정도 남으면 갱신을 해야하는데, 세번째 목차의 인증서 발급 부분부터 진행하면됩니다.

긴글 읽어주셔서 감사합니다.

Refer.

https://twpower.github.io/44-set-free-https-by-using-letsencrypt

https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04

https://velog.io/@labyu/PROJECT1-ISSUE5

https://elfinlas.github.io/2018/03/19/spring-boot-tls-certbot/

profile
경험의 연장선

0개의 댓글