反向代理伺服器啟用SSL憑證教學
前言:
網站建置時,為了保護後端伺服器或實現負載平衡,通常都會採用「反向代理(Reverse Proxy)」的方式來實作,但,有些反向代理伺服器僅支援HTTP連線,無法有效保護客戶端與伺服器之間的資料傳遞安全,如預使用HTTPS的加密連線時,就會面臨到如何設定反向代理伺服器的SSL憑證、或是否能支援多組網域名稱的SSL憑證問題。因此,本篇文章,會教你如何使用Let's Encrypt申請SSL憑證及設置反向代理伺服器。
示範說明:
一、示範的環境及網域名稱:
二、參考相關資料:
三、線上測試憑證:
四、備註:
安裝及設定方式
# cd /usr/ports/security/ca_root_nss/ && make install clean # cd /usr/ports/ftp/wget/ && make install clean # cd /usr/ports/ftp/curl/ && make install clean # cd /usr/ports/www/nginx/ && make install clean # cd /usr/ports/www/varnish5/ && make install clean # cd /usr/ports/security/hitch/ && make install clean |
# pkg install ca_root_nss wget curl nginx varnish5 hitch |
# wget --no-check-certificate https://github.com/hlandau/acme/releases/download/v0.0.59/acmetool-v0.0.59-freebsd_amd64.tar.gz # tar zxvf acmetool-v0.0.59-freebsd_amd64.tar.gz # cd acmetool-v0.0.59-freebsd_amd64 # cp -a bin/acmetool /usr/local/bin/ # chown root:wheel /usr/local/bin/acmetool |
# mkdir -p /var/log/nginx # mkdir -p /usr/local/www/acme/.well-known/acme-challenge/ # chown -R www:www /usr/local/www/acme |
# vi /usr/local/etc/nginx/nginx.conf |
user www www; worker_processes 1; events { use kqueue; worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_iso8601] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '"$host" $request_time'; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log; charset utf-8; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_names_hash_bucket_size 128; client_header_buffer_size 2k; server_tokens off; add_header X-Frame-Options SAMEORIGIN; gzip on; gzip_vary on; gzip_comp_level 3; gzip_disable "MSIE [1-6]\."; gzip_types text/xml text/plain text/css application/javascript application/x-javascript application/rss+xml; server { listen 127.0.0.1:402 default; root /usr/local/www/acme; try_files $uri $uri/ =404; access_log /var/log/nginx/acme-access.log main; error_log /var/log/nginx/acme-error.log; } } |
# vi /etc/rc.conf |
nginx_enable="YES" |
# /usr/local/etc/rc.d/nginx start |
# mkdir /usr/local/etc/varnish |
# vi /usr/local/etc/varnish/acmetool.vcl |
backend acmetool { .host = "127.0.0.1"; .port = "402"; } sub vcl_recv { if ( req.url ~ "^/.well-known/acme-challenge/" ) { set req.backend_hint = acmetool; return( pass ); } } |
# vi /usr/local/etc/varnish/default.vcl |
vcl 4.0;
import std;
### 先執行acmetool.vcl裡的vcl_recv函式
include "/usr/local/etc/varnish/acmetool.vcl";
### 根據後端網頁伺服器的 IP 修改
backend EPAPERIDVTW { .host="211.72.xxx.xxx"; .port="80"; }
backend TALKIDVTW { .host="211.72.xxx.xxx"; .port="80"; }
sub vcl_recv {
set req.http.X-Forwarded-For = client.ip;
set req.http.x-clientip = client.ip;
set req.http.x-serverip = server.ip;
set req.http.x-localip = local.ip;
set req.http.x-remoteip = remote.ip;
### 將 HTTP 的連線轉至 HTTPS
if ( std.port(local.ip) == 80 ) {
set req.http.x-redir = "https://" + req.http.host + req.url;
return( synth(850,"Moved permanently") );
}
if ( std.port(server.ip) == 443 ) {
set req.http.X-Forwarded-Proto = "https";
}
### 根據 URL 來判斷使用那一個後端伺服器
if ( req.http.host ~ "^epaper.idv.tw$" ) { set req.backend_hint = EPAPERIDVTW; }
elseif ( req.http.host ~ "^talk.idv.tw$" ) { set req.backend_hint = TALKIDVTW; }
}
sub vcl_synth {
if ( resp.status == 850 ) {
set resp.http.Location = req.http.x-redir;
set resp.status = 301;
return( deliver );
}
}
sub vcl_deliver {
call modify_http_headers;
}
### 設定及移除部分的HTTP Header參數
sub modify_http_headers {
set resp.http.Strict-Transport-Security = "max-age=31536000; includeSubDomains";
set resp.http.Server = "TWNIC-EPAPER";
unset resp.http.Via;
unset resp.http.X-Varnish;
unset resp.http.Age;
}
|
# vi /etc/rc.conf |
varnishd_enable="YES" varnishd_listen="127.0.0.1:6086,PROXY" varnishd_extra_flags="-a 210.17.xxx.xxx:80 -p feature=+http2" varnishd_config="/usr/local/etc/varnish/default.vcl" varnishd_storage="malloc,2G" varnishlog_enable="YES" varnishncsa_enable="YES" |
備註:
|
# /usr/local/etc/rc.d/varnishd start # /usr/local/etc/rc.d/varnishncsa start # /usr/local/etc/rc.d/varnishlog start |
# varnishd -C -f /usr/local/etc/varnish/default.vcl |
# /usr/local/bin/acmetool quickstart |
備註:
|
# crontab –e |
27 13 * * * /usr/local/bin/acmetool --batch reconcile |
# openssl dhparam -rand - -out /var/lib/acme/conf/dhparams 2048 # /usr/local/bin/acmetool want epaper.idv.tw # /usr/local/bin/acmetool want talk.idv.tw |
# /usr/local/bin/acmetool status |
# mkdir -p /var/lib/hitch # chown -R nobody:nobody /var/lib/hitch |
備註:
|
# vi /usr/local/etc/hitch.conf |
frontend = "[210.17.xxx.xxx]:443" backend = "[127.0.0.1]:6086" write-proxy-v2 = on ciphers = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH" pem-file = "/var/lib/acme/live/epaper.idv.tw/haproxy" pem-file = "/var/lib/acme/live/talk.idv.tw/haproxy" workers = 4 alpn-protos = "h2,http/1.1" ocsp-verify-staple = on ocsp-dir = "/var/lib/hitch" |
備註:
|
# vi /etc/rc.conf |
hitch_enable="YES" |
# /usr/local/etc/rc.d/hitch start |
# sockstat -l |
測試
# curl -I https://epaper.idv.tw # curl -I https://talk.idv.tw |
備註:使用curl指令來檢查連線是否正常、及HTTP Header是否有變更? |