Caddy + synology: reverse proxy와 tls 적용하기

Caddy + synology: reverse proxy와 tls 적용하기

이전에도 살짝 언급했다시피 나는 reverse proxy를 사용하여 서비스를 연결한다. 현재 서버의 reverse proxy로는 opnsense에서 플러그인으로 제공하는 caddy web server 플러그인을 사용하고 있다. gui로 대부분의 기능을 지원하여 사용하기 편리하기 때문에 세세한 설정이 필요하지 않으면 가볍게 설정하기 아주 유용하다.

synology는 유명한 NAS 제조업체이고, 현재 나는 시놀로지를 포팅한 헤놀로지를 proxmox에 올려서 사용하고 있다. 현재는 파일 공유서버로만 사용하고 있고, 외부에서는 webdav만 사용하고 있다. synology 내에도 reverse proxy 기능이 존재하는데 굳이 opnsense의 caddy 플러그인 사용한 이유는 들어오는 모든 트래픽을 opnsense를 지나가도록 만들고, 트래픽을 관리하도록 만들고 싶어서였다. caddy를 이용해 reverse proxy를 적용하는 것은 쉽게 했으나 tls/ssl을 적용하는 것은 삽질을 많이 했다. tls를 적용하고 싶은 사람에게 도움이 될 수 있도록 정보를 공유하고자 한다.

https와 ssl/tls란?

Hypertext Transfer Protocol (HTTP)는 웹 브라우저와 웹사이트간 전송 프로토콜로 다 한번씩은 보았을 것이다. 인터넷 주소 앞에 http://라고 표현된 것이 HTTP이고, 이를 암호화하여 보안을 강화한 버전이 Hypertext Transfer Protocol Secure (HTTPS)이다.

HTTP와 HTTPS의 차이

HTTPS가 HTTP에 보안을 적용했다고 했는데 여기에서 보안을 적용하는 방법을 Secure Socket Layer(SSL)과 Transport Layer Security(TLS)라고 한다. SSL과 TLS가 동작하는 방법은 주제에서 벗어나니 생략하고, HTTPS를 적용해야 암호화해서 데이터를 보내기 때문에 외부에 공개되어도 허가되지 않은 사람이 감청할 수 없어 안전하다. SSL을 적용하기 위해선 인증서가 필요한데 요즘에는 자동으로 발급할 수 있는 방법이 많다.

Reverse proxy와 SSL termination/SSL passthrough

Reverse proxy란 외부의 클라이언트와 서버 중간에 컴포넌트를 하나 둬서 서버와 클라이언트가 직접적으로 통신하지 않게 만든다.

reverse proxy 동작방식

그림으로 설명하면 클라이언트가 www.example.com으로 웹서버를 접속하려고 할 때 서버와 직접적으로 통신하는 것이 아닌 reverse proxy에서 먼저 통신을 하고 이를 웹서버의 내부 ip(192.0.2.44:3000)로 보내주는 역할을 한다. 이를 통해 서버를 운영하는 입장에서는 공유기나 방화벽 포트를 80, 443 포트만 열어주면 된다는 점이 하나 있고 (FTP 같은 다른 서비스를 쓰지 않는 이상) 클라이언트 입장에서는 포트 번호를 뒤에 쓸 필요 없이 url만 써서 서버에 접속 가능한 이점이 있다.

SSL passthrough와 SSL offloading의 차이

기본적으로 reverse proxy를 사용하면 reverse proxy와 서버내에서의 통신은 안전하다는 가정이 들어가므로 http로 통신하게 된다. 즉, 인터넷과 reverse proxy 사이의 통신은 HTTPS로 하고, reverse proxy와 서버 내 통신은 HTTP로 하게 된다. 이를 SSL offloading이라고 한다. 그러나, 서비스 자체에 HTTPS를 지원한다던지 (synology의 경우) 필요에 의해 내부망에서도 HTTPS를 적용하고 싶다면 내부망까지 HTTPS로 통신해야 하는데 이를 SSL passthrough라고 한다.

OPNSense caddy로 reverse proxy 적용하기 (SSL offloading)

Opnsense caddy plugin을 사용하기 위해 우선 기본 설정부터 적용해준다. 기본적으로 도메인은 가지고 있다고 가정하겠다. caddy는 SSL 인증서를 Let's encrypt나 zeroSSL로 자동으로 발급해준다. 이를 위한 email을 ACME Email 부분에다가 적어준다.

Let's encrypt 이메일 적용

이후 DNS Provider 탭에 들어가 DNS를 설정해준다. 나는 cloudflare에 도메인을 구매해놓아서 cloudflare로 설정해주었다. DNS API Standard Field에는 cloudflare에서 발급한 토큰을 입력해주면 되는데 토큰 발급 방법은 링크로 대체한다.

다음은 reverse proxy 적용 방법에 대해 설명한다. reverse proxy 탭에 들어가 도메인을 누르고 도메인 항목에 사용할 주소를 적는다. 이번엔 예시로 이 블로그의 주소를 적어보겠다. 설명은 Opnsense에서 구분할 목적으로 적는 것으로 작동에 영향을 주지 않는다.

도메인 항목 설정

이후에 HTTP handler로 들어가 추가로 설정 해준다. 도메인은 도메인 항목에서 설정한 항목을 눌러주면 되고, upstream에 연결을 원하는 웹서버의 내부 ip와 연결할 포트를 설정해주면 된다.

HTTP handlers 항목 설정

이렇게 되면 외부에서 접속할 때 Let's encrypt로 발급받은 인증서가 보이고, HTTPS로 연결되지만, 내부에서는 HTTP로 연결되는 SSL Offload 상태가 된다.

외부에서는 HTTPS로 통
내부는 HTTP로 통신

SSL Passthrough로 적용하기

헤놀로지의 경우 HTTP 연결과 HTTPS 연결 둘다 적용이 가능하다. 이번엔 헤놀의 HTTPS 연결과 reverse proxy를 사용해 내부망까지 HTTPS를 적용해보자.

이를 위해 우선 시놀로지의 기본 자체발급 인증서를 다운로드 받아야한다. 자체 발급 인증서는 제어판 ➡ 보안 ➡ 인증서 탭으로 가면 볼 수 있고, 작업 ➡ 인증서 내보내기를 눌러 다운로드 받을 수 있다.

다음으로 opnsense로 돌아가서 시스템 ➡ 신뢰성 ➡ 권한 으로 들어간다. +를 누른 후 인증서 편집에서 기존 인증 기관 가져오기를 누른다. 인증서 데이터에는 cert.pam의 부분을 전부 복사하면 되고, 개인 키 데이터에는 private.pam의 내용을 전부 복사해주면 된다. Begin 부분과 End 부분 모두를 복사해주고 저장한다.

자체 인증서 설정

다시 caddy로 돌아가 HTTP handler 설정을 해준다. 위에서 설정한 방식에 추가로 신뢰성 탭을 눌러서 TLS를 체크 해준다. 그리고 TLS Trust Pool에 위에서 작성해준 권한 인증서를 선택한다. TLS server name에는 발급 주체인 synology를 적는다. 인증서를 만들 때 이름의 CN부분을 적으면 된다.

SSL Passthrough HTTPS 설정

그러면 이전과 다르게 내부망에서도 TLS가 적용되어 있는 모습을 확인할 수 있다.

마무리

TLS를 적용하는 방법은 이외에도 HTTP-01 챌린지, DNS-01 챌린지 등 다양한 방법이 있다. HTTP-01 챌린지의 경우 caddy에서 발급해주는 인증서가 아닌 서버에서 발급한 인증서로 외부에서 HTTPS를 인증하는 방식으로 이해하고 있는데 처음에는 시놀로지에 이렇게 적용해보았다가 다른 서비스에 적용하기 곤란해 현재의 방식으로 바꾸었다.

다음 글은 Authentik을 이용한 SSO 적용과 caddy 연동에 관한 글을 쓸 예정이다.

References

HTTPS란? (동작방식, 장단점)

SSL이 적용된 로드밸런서에서의 호스트 기반 라우팅 동작 방식

Caddy: Reverse proxy에서 Reverse Proxy the OPNsense WebGUI 항목