Cloudflare DNS 서비스를 통해 Let's Encrypt 인증서 발급 및 갱신 자동화하고 v2-ui에 http+tls 위장 적용하기

한동안 한국 정부가 DNS Spoofing 및 SNI 필드 감청으로 불법 사이트 접속을 막으면서 여러가지 논란이 되었는데, 중국 정부는 더하면 더했지 덜하지는 않습니다.
중국 만리방화벽이 어떤 식으로 작동하는지는 관계자가 아니면 아무도 모르겠지만, 기본적으로 중국내에서는 모든 네트워크 트래픽을 감시한다고 보는게 맞을 겁니다.

중국 정부가 만리방화벽을 통해 접근을 막고 있는 사이트에 접속하기 위해서 사용하는 여러가지 방법들 중 네트워크 트래픽을 보안이 적용된 웹사이트 (HTTPS = HTTP + TLS)에 접속하는 트래픽으로 위장하여 차단을 막는 방법이 최근에 많이 사용됩니다.

10여년 전에 정보처리기사 자격증 딸 때 이후로 네트워크쪽으로 전혀 공부해 본 적이 없어서 자세히 설명할 수는 없지만, 간단히 개념만 설명해 보겠습니다.

http는 HyperText Transfer Protocol의 약자로 웹상의 데이터를 주고 받기 위한 전송 규약으로 이해하면 됩니다.
tls는 Transport Layer Security의 약자로 네트워크 전송 데이터를 암호화 하여 데이터를 중간에 가로채더라도 내용을 열어볼 수 없게 하는 목적의 기술입니다.

위 두가지를 합해서 웹 상에서 중요한 데이터를 주고 받을 때 사용하는 프로토콜을 https (HTTP over TLS)라고 하며 전자상거래 등의 보안이 중요한 사이트에 연결 시 사용합니다. 즉, 일반적인 http를 사용하는 웹사이트 접속은 중간에 네트워크 데이터를 가로채서 내용을 확인할 수 있지만, https를 통한 웹사이트 접속은 중간에 네트워크 데이터를 가로채더라도 인증서를 통한 개인키가 없으면 내용을 확인할 수 없습니다.

v2ray에서 https를 통한 위장은 다음과 같습니다.
VPS에 설정한 v2ray 프록시 서버의 연결 포트를 https가 기본적으로 사용하는 443 포트로 설정하고, v2ray 클라이언트가 접근이 막힌 사이트에 접속하기 위해 경유지인 v2ray 프록시 서버에 보내는 데이터를 v2ray 프록시 서버에 연결된 정식 인증서를 받은 도메인의 공개키로 암호화하여 전송하여, 중간에 만리방화벽이 데이터를 가로채더라도 해당 데이터가 일반적인 https 사이트에 접속하기 위해 주고받는 데이터로 인식되도록 하여 검열을 피하도록 하는 방식으로 이해하면 됩니다.

http+tls 트래픽 위장을 위해서는 아래 준비물이 필요합니다.

  1. 정식 도메인 : DDNS 등으로 발급받은 도메인은 소유권이 본인에게 없어 인증서 발급이 불가하므로 본인이 인증서 신청 및 발급이 가능한 도메인이 필요합니다.
  2. SSL/TLS 인증서 : 인증서는 서버와 클라이언트가 서로의 신원을 확인하기 위해서 사용하며, 인증기관(CA, Certificate Authority)이 발행합니다. 보통 신뢰할 수 있는 인증기관에서 SSL/TLS 인증서를 발행받는데에는 비용이 필요하나, 우리는 Let's Encrypt에서 발행하는 3개월 유효기간의 무료 인증서를 받아서 사용할 예정이며, Cloueflare의 무료 DNS 관리 서비스를 이용하여 3개월 유효기간 만료 전 자동으로 인증서를 갱신받도록 설정할 예정입니다.

도메인 가입

도메인의 경우는 등록된 도메인을 네임서버 변경하여 Cloudflare 무료 DNS 관리 서비스를 이용할 예정이므로, 구매 자체는 아무 곳이나 저렴한 곳에서 구매하시면 됩니다.

Cloudflare 가입 및 도메인 연결

본인이 소유 중인 도메인을 Cloudflare에 연결하기 위해서 우선 Cloudflare에 가입합니다.

가입 및 로그인 하시면 Dashboard(https://dash.cloudflare.com)가 표시되며, 파란색 "+ Add a site" 버튼을 눌러 본인이 소유중인 도메인 주소를 입력합니다.
제 경우에는 이미 등록되어 현재 사용중인 szkorean.net 상단 홈페이지 로고 옆에 표시되어 있는 걸 볼 수 있습니다.
Cloudflare 대시보드


도메인 입력



도메인 주소를 입력하고 나면 결제 조건을 선택하는데, 일단 도메인 관리만 할 예정이므로 제일 좌측 무료 옵션을 선택합니다.
결제 옵션

잠시 도메인 상황을 검토한 후 아래와 같은 분석 내용을 보여줍니다.
기존에 이미 도메인 관련 A레코드나 CNAME, MX, TXT 레코드 등을 설정한 적이 있으면 해당 내용들을 자동으로 가져와 보여줍니다. 경우에 따라 가져오지 못하는 값들도 있을 수 있습니다. 혹시 가져오지 못한 값이 있는 경우 기존 도메인을 구입한 사이트의 도메인 관리 옵션에서 레코드 이름과 값을 확인하여 입력해 줍니다.
기존 도메인 관리 사이트에서 네임서버를 Cloudflare로 변경한 이후에는 위 레코드 값을 확인하지 못할 수 있으므로 가능하면 네임서버 변경 전에 기존 값을 별도로 적어두거나 하는 것이 좋습니다.

기존 도메인 설정 읽어오기


저는 Oracle Cloud에서 운영 중인 CentOS 7에서 돌아가는 v2-ui 서비스에 인증서를 적용할 예정이며 A 레코드 만 적용한 상태로 Proxy Status 항목은 구름 아이콘을 클릭하여 전부 다 DNS resolution only로 설정했습니다. Proxy Status 항목 설명은 아래와 같이 설명되어 있습니다.

Proxy traffic for A, AAAA, and CNAME records by clicking the cloud icon.

Proxied: Accelerates and protects traffic

DNS resolution only: Bypasses Cloudflare


설정을 마친 후에는 목록 최하단의 파란색 "Continue" 버튼을 눌러서 다음으로 넘어갑니다.

네임 서버 변경

현재 도메인은 기존 도메인 관리 사이트의 Name Server를 사용중이기 때문에 Cloudflare에서 도메인을 관리하기 위해서는 Name Server를 변경해야 합니다.
위와 같이 현재 도메인의 네임서버 설정을 표시해 주고, 이후 Cloudflare에서 도메인을 관리하기 위해서 새로 변경할 Name Server 주소를 표시해 줍니다.
기존 도메인 관리 사이트에 로그인 한 후 네임서버 변경 기능을 이용해 1,2번 네임 서버를 변경합니다.

도메인 관련 설정을 변경하면 이 내용이 인터넷 전체에 전파되는데, 시간이 소요되기 때문에 보통 24시간 이내에 변경사항이 적용된다고 안내하는데, 빠르면 바로 적용될 때도 있으니 너무 오래 기다릴 필요는 없습니다.

"Done, check nameservers" 버튼을 클릭해서 다음으로 넘어간 후 보안 설정 관련해서는 특별히 변경사항 없이 제일 하단 "Done"버튼을 클릭하여 설정을 마칩니다.

Cloudflare에 연결된 도메인의 인증서를 Let's Encrypt를 통해 3개월마다 갱신할 때 매번 사이트에 접속하여 갱신할 필요없이 자동으로 갱신하도록 하기 위해서 Linux 서버에서 script를 통해서 명령어로 인증서 발급 및 갱신이 되도록 설정할텐데, 이 때 Cloudflare의 Global API Key가 필요합니다.

Cloudeflare에 로그인 된 상태에서 우측 상단의 사용자 아이콘 -> My Profile -> API Tokens -> Global API Key 의 "View" 버튼을 눌러 표시되는 문자열을 따로 복사해둡니다.
Global API Key

VPS 설정


도메인을 Cloudflare에 연결하였고, Global API Key를 확인하였으면 이제 Linux에서 도메인 인증서를 발급받고, 이를 v2-ui에 적용하도록 하겠습니다.

Cloudflare 연결 API 파일 작성

우선 사용하는 VPS 서버에 로그인하고 root권한을 획득합니다.

Cloudflare에서 관리하는 도메인에 접근하기 위한 설정 파일을 홈 디렉토리 밑에 하나 만들겠습니다. 제 경우는 oracle cloud 홈 디렉토리에 만들었는데, 기억할 수 있는 아무곳에 만들어도 됩니다.
mkdir /home/opc/.secrets
nano /home/opc/.secrets/certbot.ini

위와 같이 디렉토리를 하나 만들고 그안에 설정 파일을 하나 만들어 편집합니다. (certbot.ini 파일 이름은 본인이 원하는 이름으로 작성하면 됩니다.)

아래와 같이 nano에서 내용을 입력한 후 Ctrl+X를 눌러 파일을 저장하고 빠져나옵니다.
메일주소와 Global API Key 부분에 Cloudflare에 등록한 이메일 주소와 앞에서 복사해 놓은 본인의 Global API Key를 붙여넣습니다.
dns_cloudflare_email = 메일주소
dns_cloudflare_api_key = GlobalAPIKey

혹시 모르니 root 유저만 접근할 수 있도록 권한을 조정합니다.
chmod 0400 /home/opc/.secrets
chmod 0400 /home/opc/.secrets/certbot.ini

인증서 발급/갱신용 프로그램 Certbot 설치

Let's Encrypt에서 인증서를 발급받기 위한 Certbot을 아래 링크와 같은 방법으로 설치합니다.

본인이 사용하는 서버에서 웹서버를 운영하는 경우 웹서버 및 OS 종류를 선택하면 하단에 설치 방법이 표시됩니다.
웹서버를 운영하지 않는 경우 "None of the above"를 선택하면 됩니다.
웹서버를 운영하는 경우 설치 방법에 따라 자동으로 웹서버에 인증서를 적용하고, 인증서 갱신 시 웹 서버를 중단하고 인증서 갱신 후 웹서버를 재시작 하는 등의 자동화가 가능하니 본인 서버 운영환경에 맞춰 설치하시면 됩니다.

저는 CentOS7이 운영되는 VPS에 v2-ui에서 직접 인증서 경로를 지정하여 적용할 예정이므로 아래와 같이 Certbot 및 Cloudflare 플러그인을 설치합니다.
yum install epel-release
yum install certbot
yum install python2-certbot-dns-cloudflare

ubuntu (16.04, 18.04)인 경우에는 아래 명령어로 설치합니다.
apt-get update
add-apt-repository ppa:certbot/certbot
apt-get update
apt-get install certbot
apt-get install python3-certbot-dns-cloudflare

인증서 발급

아래 명령어로 Certbot을 이용해 인증서를 발급받습니다.
certbot certonly --dns-cloudflare --preferred-challenges dns-01 --dns-cloudflare-propagation-seconds 30 --dns-cloudflare-credentials /home/opc/.secret/certbot.ini -d 도메인주소

certonly subcommand로 인증서만 발급받도록 하였고,
--dns-cloudflare옵션으로 Cloudflare를 이용하도록 하고,
--preferred-challenges dns-01 옵션으로  DNS 레코드 확인 방법으로 DNS 소유 여부를 확인하도록 설정,
--dns-cloudflare-propagation-seconds 30은 DNS에 레코드 생성후 30초 기다렸다가 DNS에 생성된 레코드를 확인한다는 옵션입니다.
--dns-cloudflare-credentials 옵션 뒤에 위에서 만들어준 Cloudflare 연결 설정 파일의 절대 경로를 적어줍니다.
-d 옵션 뒤에는 본인 VPS에 연결된 도메인 주소를 적어주면 되고, test.example.com, example.com, *.example.com 과 같은 형태로 도메인을 지정할 수 있으며, 여러개의 도메인에 대해서 한번에 인증서를 받으려면 -d 옵션을 중복으로 사용할 수 있습니다.

위 명령어를 입력하면 아래와 같이 몇가지 정보를 입력해야 합니다.
갱신이나 보안 관련 연락을 받기 위한 이메일 주소
이메일 입력

약관에 동의 여부 ("a" 또는 "A" 입력)
약관 동의

입력한 이메일로 Certbot을 개발한 비영리기관 Electronic Frontier Foundation(EFF)의 정보성 메일을 수신할지의 여부를 입력합니다. (필요에 따라 "y" 또는 "Y", "n" 또는 "N"을 입력)
정보성 메일 수신 여부

위에서 지정한 옵션에 따라 인증서 생성이 완료되면 아래와 같이 생성된 인증서 파일의 경로 및 인증서 만료일이 언제인지 표시됩니다.
생성 결과 메시지

인증서 자동 갱신

발급된 인증서는 유효기간이 30일이므로 만료되기 전에 갱신을 해야 하는데, 이를 자동화 하기 위해서 아래 명령을 실행하여 root 계정에 crontab 작업을 추가합니다.
echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | sudo tee -a /etc/crontab > /dev/null

매일 0시, 12시가 되면 임의의 1시간 이내에 certbot renew -q 명령어를 실행하여 인증서 갱신을 요청합니다. 인증서가 만료기간이 도래하지 않은 경우 아무일도 일어나지 않기 때문에 매일 12시간 마다 한번씩 위 갱신 명령어를 실행하게 되며, 전세계 모든 Certbot 사용자가 매일 0시, 12시 정각에 갱신을 요청하게 되면, Let's Encrypt 서버에 과도한 부하가 걸리기 때문에 python 명령어로 난수를 발생시켜 1시간 이내의 지연 시간을 두고 갱신 요청을 하는 명령어입니다. 위 0,12의 시간 부분을 다른 시간으로 변경해도 무방합니다. (Ex. 3,15로 입력하면 오전 3시, 오후 3시에 갱신 시도)

crontab 작업이 정상적으로 추가되었는지 확인하기 위해서 crontab -l 명령어를 실행하면, 위 echo 명령어 뒤의 " "로 둘러싸인 문장 중에서 중간에 root를 제외한 문장이 출력되어야 하며, root 사용자의 crontab 작업이 없다는 메시지가 출력되면 반복 작업이 제대로 추가되지 않은 것이므로 crontab -e 입력한 후 편집기가 뜨면 아래 내용을 입력하고 저장하면 됩니다.
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q

Ubuntu(16.04, 18.04)의 경우는 Certbot으로 인증서를 발급 받으면 자동으로 cron 작업이 추가됩니다.
아래는 18.04에서 인증서 발급 받은 뒤 자동으로 생성된 /etc/cron.d/certbot 파일의 내용입니다.
Ubuntu 자동 cron작업 추가 내용


v2-ui Web UI에 인증서 적용 및 Proxy 생성 시 인증서 이용하여 HTTP+TLS 위장 적용하기

Web UI에 인증서 적용

사실 Web UI에 적용하지 않아도 무방한데, 인증서가 제대로 작동하는지 테스트하기 위해서 Web UI에 적용해 보겠습니다.

본인의 VPS에 설치한 v2-ui Web UI에 웹 브라우저를 이용해 접속합니다.
좌측 메뉴의 panel settings에 들어가서 SSL cert file path 및 SSL key file path를 서버 상의 절대 경로로 입력합니다. 혹시 잘못 입력하면 v2-ui Web UI에 접속 자체가 안될 수 있으므로 경로 입력시 유의하시기 바랍니다. 혹시 잘못 입력해서 Web UI 접속이 안되는 경우 리눅스 명령줄에서 v2-ui 명령을 통해 설정을 초기화 하고 재설정 해야 합니다.
v2-ui 인증서 경로 지정


경로 지정이 끝나면 업데이트에 성공했다는 메시지가 잠시 표시됩니다. 현재는 웹 UI를 표시하는 웹서버가 재시작 되지 않을 상태이기 때문에 아직 인증서가 적용되지 않은 상태입니다.

VPS 명령줄에서 v2-ui restart 명령어를 입력하여 v2-ui를 재시작해 줍니다.
v2-ui restart

v2-ui 재시작후 다시 브라우저에서 Web UI 주소를 입력하면 연결이 안될 수 있습니다. 이미 인증서가 적용되어 있으므로 주소 입력시 https://를 추가로 입력하여 접속해야 로그인 페이지가 표시되며, 브라우저의 주소 입력란 앞에 자물쇠가 표시되어 https 프로토콜로 보안 연결된 상태로 표시됩니다.
크롬 브라우저의 경우 아래와 같이 인증서 적용 전과 후의 보안 연결 상태를 확인할 수 있습니다.
SSL 적용 전,후 크롬 주소표시줄

V2ray proxy에 인증서 적용 위장하기

Web UI 좌측 메뉴에서 accounts 메뉴를 선택하여 Proxy 관리 메뉴에 들어가서 기존에 만들어두었던 v2ray(vmess) Proxy 항목의 연필 모양 수정 버튼을 클릭하거나, 새로 v2ray proxy항목을 만들기 위해 파란색 + 버튼을 클릭합니다.

TLS 위장 설정

V2ray가 연결할 포트는 TLS를 사용하는 사이트가 주로 사용하는 443으로 설정합니다. 이 포스팅 제일 위에서 얘기한 것과 같이 Proxy로 가는 트래픽을 https 프로토콜로 보안 연결되는 사이트로 가는 트래픽인 것 처럼 위장하는 것이기 때문에 https 연결에서 가장 많이 사용하는 443으로 설정하는 것이 좋습니다.

Transport 설정은 ws 또는 http로 설정합니다. 위 두가지 옵션은 전송 방식의 차이일 뿐 나머지는 큰 차이가 없다고 보시면 됩니다.

TLS 옵션을 켜고, 인증서를 발급받은 도메인명, 인증서 및 키 파일의 절대 경로를 입력해주고 "add" (기존 항목 수정인 경우 "update") 버튼을 눌러서 적용합니다.

이제 위와 같이 설정한 v2ray proxy로 연결하는 경우 데이터가 암호화되어, 설정한 도메인으로 가는 트래픽인 것처럼 위장되므로 중국 만리방화벽에 의해 탐지될 가능성이 좀 더 낮아집니다.

추가

중국 만리방화벽이 어떤 식으로 작동하는지는 모르지만 일부 사람들은 실제 해당 도메인에 리버스 프록시를 사용해서 별 내용 없더라도 실제 연결되는 사이트를 운영하는 것이 방화벽에 탐지될 가능성이 낮아진다고 하는 사람도 있는데, 저는 일단 이렇게 운영하다가 탐지되어 막힌다고 판단되는 경우 리버스 프록시 설치, 운영하는 방안을 생각 중입니다.

혹시 틀린 내용이나 제가 잘못 알고 있는 부분이 있으면 Feedback 부탁드립니다.

댓글

이 블로그의 인기 게시물

OpenWrt 공유기에 Wireguard 설정하기

샤오미 공유기 3세대(Mi Router R3G)에 OpenWrt 올리기