http 使用 80 port 進行資料傳輸,這些資料使用明碼在網路上到處流竄,很容易被駭客攔截盜用。所以最安全的作法就是使用 https 443 port,藉由 SSL 將資料加密後才傳出。
SSL 全名為 Secure Sockets Layer,由 Netscape 在1994 年推出。伺服器與客戶端之間的通訊,皆經過加密才傳遞,所以就算訊息被攔截,攔截者也只會看到一堆亂碼而以,完全無法解碼。
底下的說明設定,完全以 Linux 為主,不適用於 Windows。
自行簽署 SSL 憑証
自行簽署的憑証的方法如下
sudo mkdir /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
然後依序如下填入相關訊息
Country Name (2 letter code) [AU]:TW State or Province Name (full name) [Some-State]:Taiwan Locality Name (eg, city) []:Changhua Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyCompany Organizational Unit Name (eg, section) []:MyUnit Common Name (e.g. server FQDN or YOUR name) []: mahaljsp.asuscomm.com Email Address []:mahaljsp@gmail.com
將 /etc/nginx/sites-available/default 改成如下
server {
listen 80;
listen [::]:80;
rewrite ^(.*) https://mahaljsp.asuscomm.com permanent;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name mahaljsp.asuscomm.com;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
...
}
最後記得重啟 nginx
sudo systemctl restart nginx
上述 nginx 設定,會自動將 http 80 port 轉交 443 port,這樣客戶端輸入 http://mahaljsp.asuscomm.com 時,就不會出現找不到網頁的情形。
不過因為這是自已簽署的 SSL 憑証,客戶端還是會出現私人網站不安全的訊息,要解決此問題,請接續下面的設定。
Let’s Encrypt 免費憑証
自已產生 SSL 憑証,在瀏覽網頁時會出現私人不安全的警告,所以必需使用第三方產生的憑証。大部份的第三方憑証都要年費,什麼都要錢,網域也要錢,憑証也要錢,架個網頁搞到傾家蕩產。
還好有 Let’s Encrypt 可以免費使用,不過憑証的有效期限只有三個月,所以每三個月就要產生一次新的憑証。這個免費憑証有多個限制,影響比較大的是每秒不能超過 20 次驗証請求。不過這種流量通常只有大型網站才可能達到,一般網站就不用擔心。
請進入 Let’s Encrypt 選擇 Nginx 及 作業系統,就會跳出安裝 SSL 的說明。底下將說明如何在 Linux 下安裝憑証。
Nginx設定
先將 nginx 設定好,記得 server name 一定要寫好網域名稱。最後記得一定要把 ip 分享器 443 port 指向 Linux 這台 Server 的 虛擬 IP,這樣 Let’s Encrypt 才能連進來進行驗証。
安裝
使用底下指令安裝 “certbot”,此套件會安裝在 /snap/bin/下,再將 certbot 在 /usr/bin/certbot 建立軟連結。
sudo snap install --classic certbot sudo ln -s /snap/bin/certbot /usr/bin/certbot
第一次執行 certbot
使用底下指令執行 certbot
sudo certbot --nginx
第一次執行時,會要求輸入 eMail 及同意相關規定,並選擇要設定憑証的網站,如下
Saving debug log to /var/log/letsencrypt/letsencrypt.log Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): mahaljsp@gmail.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must agree in order to register with the ACME server. Do you agree? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing, once your first certificate is successfully issued, 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 our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y Account registered. Which names would you like to activate HTTPS for? We recommend selecting either all domains, or all domains in a VirtualHost/server block. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1: mahaljsp.ddns.net 2: mahaljsp.asuscomm.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Select the appropriate numbers separated by commas and/or spaces, or leave input blank to select all options shown (Enter 'c' to cancel): 1 2 Requesting a certificate for mahaljsp.ddns.net
執行完 certbot 將憑証放在 /etc/letsencrypt/live/xxx.ddns.net 目錄下。憑証有二個,分別為 fullchain.pem及privkey.pem。而且會自動更改 Nginx 的設定檔,並自已重新啟動 nginx。
更改後 Nginx 內容
Nginx 設定檔會被更改成如下
server { if ($host = mahaljsp.ddns.net) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name mahaljsp.ddns.net; rewrite ^(.*) https://mahaljsp.ddns.net permanent; } server { listen 443 ssl; listen [::]:443 ssl; ssl_certificate /etc/letsencrypt/live/mahaljsp.ddns.net/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/mahaljsp.ddns.net/privkey.pem; # managed by Certbot server_name mahaljsp.ddns.net; location / { proxy_pass http://localhost:7001; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
...........
}
自動更新憑証
憑証的有效日期只有三個月,每以我們使用 Linux 排程器 crond 每個月的 1 日 0:0 更新一次憑証。在 /etc/cron.d 之新增 renewssl 檔案,內容如下
0 0 1 * * root certbot renew --dry-run >> /home/thomas/renew_ssl.log
最後重啟 cron
sudo service cron reload 或是 sudo /etc/init.d/cron restart 或是 sudo systemctl restart cron
Django CSRF
更改成 https 後,Django 的 CSRF 會一直無法驗証,需於 Django 的 settings.py 增加一行如下
CSRF_TRUSTED_ORIGINS = [https://xxx.ddns.net]