Let’s Encrypt給你的網(wǎng)站穿上HTTPS的鎧甲,防止http劫持

一切從劫持開始說起

在家上網(wǎng)瀏覽網(wǎng)頁,第一次打開瀏覽器,輸入網(wǎng)址,回車,發(fā)現(xiàn)頁面右下角會出現(xiàn)一個大概300x300(像素)左右大小的正方形小窗口。窗口內(nèi)多半是一些此時此刻非常不愿意看到的內(nèi)容,比如廣告。咦,我訪問的明明是某知名搜索引擎啊,按常理來說這個位置不應(yīng)該出現(xiàn)這樣一個和頁面布局極其不搭的小窗口的,是不是我中毒了?
自己運營了一個博客,放到公網(wǎng)分享內(nèi)容給大家,流量還不錯,可是留言區(qū)老有用戶說我亂打小廣告。我不信,打開瀏覽器訪問了下自己的博客,怎么搞的?我的主頁面上下左右被嵌入各種無恥下流骯臟邪惡小廣告,而且與我發(fā)布的內(nèi)容極其不和諧,有些彈窗甚至擋住了重要的內(nèi)容,可是我明明沒有接入任何廣告???
如果遇到如上兩種情況,那么恭喜你,你被http劫持了?。?!

在用戶的客戶端與其要訪問的服務(wù)器經(jīng)過網(wǎng)絡(luò)協(xié)議協(xié)調(diào)后,二者之間建立了一條專用的數(shù)據(jù)通道,用戶端程序在系統(tǒng)中開放指定網(wǎng)絡(luò)端口用于接收數(shù)據(jù)報文,服務(wù)器端將全部數(shù)據(jù)按指定網(wǎng)絡(luò)協(xié)議規(guī)則進(jìn)行分解打包,形成連續(xù)數(shù)據(jù)報文。
用戶端接收到全部報文后,按照協(xié)議標(biāo)準(zhǔn)來解包組合獲得完整的網(wǎng)絡(luò)數(shù)據(jù)。其中傳輸過程中的每一個數(shù)據(jù)包都有特定的標(biāo)簽,表示其來源、攜帶的數(shù)據(jù)屬性以及要到何處,所有的數(shù)據(jù)包經(jīng)過網(wǎng)絡(luò)路徑中ISP的路由器傳輸接力后,最終到達(dá)目的地,也就是客戶端。
HTTP劫持是在使用者與其目的網(wǎng)絡(luò)服務(wù)所建立的專用數(shù)據(jù)通道中,監(jiān)視特定數(shù)據(jù)信息,提示當(dāng)滿足設(shè)定的條件時,就會在正常的數(shù)據(jù)流中插入精心設(shè)計的網(wǎng)絡(luò)數(shù)據(jù)報文,目的是讓用戶端程序解釋“錯誤”的數(shù)據(jù),并以彈出新窗口的形式在使用者界面展示宣傳性廣告或者直接顯示某網(wǎng)站的內(nèi)容。

以上內(nèi)容摘自百度百科:http劫持

如果你去搜索引擎查找問題和答案,通常會找到如下關(guān)鍵詞:

  • 運營商劫持廣告
  • 運營商http劫持
  • http劫持
  • 電信劫持廣告
  • 電信劫持
  • 電信網(wǎng)頁劫持
  • 電信http劫持
  • 內(nèi)容劫持
  • ISP hijacking

有人說這是天朝特有的,那是因為你只活在天朝,難道國外就沒有了嗎?劫持技術(shù)是通用的。

看看如何防范

這里我們不具體聊https的原理了,就說說如何用免費的Let’s Encrypt來具體實踐如何將你的站點https化。

Let's Encrypt

Let's Encrypt是由EFF、Mozilla、Cisco、Akamai、IdenTrust與密西根大學(xué)研究人員共同創(chuàng)立的免費的憑證中心,目的在于推動全球所有的網(wǎng)站都使用HTTPS加密傳輸,并由非營利的網(wǎng)際網(wǎng)路安全研究組織Internet Security Research Group(ISRG)負(fù)責(zé)營運。
這個組織的主要原則是:

  • 免費:任何域名所有者都可以零費用申請到一個針對其域名的有效證書。
  • 自動:整個證書注冊過程在服務(wù)器安裝或配置過程中可以簡單實現(xiàn),而更新過程更是可以在后臺自動執(zhí)行。
  • 安全:Let’s Encrypt 將會提供業(yè)界最新的安全技術(shù)和最好的實踐。
  • 透明:所有關(guān)于證書發(fā)放、撤銷的記錄都會向任何需要調(diào)查的人員開放。
  • 開放:自動化執(zhí)行的發(fā)放和更新協(xié)議將會是開放標(biāo)準(zhǔn),軟件也盡可能使用開源軟件。
  • 合作:與現(xiàn)有的互聯(lián)網(wǎng)協(xié)議本身很相似,Let’s Encrypt 是一個對整個社區(qū)都有益的聯(lián)合行動,不由任何一個組織控制。

下面聊聊具體的實踐故事

首次生成證書


從Github簽出Let’s Encrypt的源代碼

git clone https://github.com/letsencrypt/letsencrypt

進(jìn)入本地源代碼目錄

cd letsencrypt

Let’s Encrypt提供多種認(rèn)證方式,因為之前在VPS上有了HTTP的網(wǎng)站,所以這里采用了webroot的方式,其他方式請參考官方文檔
如果是主域名的認(rèn)證:

./letsencrypt-auto --debug certonly --webroot --email name@your_main_domain.com -d www.your_main_domain.com -d your_main_domain.com -w /var/www/your_main_domain.com

子域名的認(rèn)證:

./letsencrypt-auto --debug certonly --webroot --email name@your_main_domain.com -d subdomain.your_main_domain.com -w /var/www/your_main_domain.com/subdomain

然后在彈出的藍(lán)底白字提示框中一路點擊"OK"

注意如下問題:

  • 請將命令中的name, your_main_domain.com, subdomain替換成你自己的名字,域名以及子域名
  • 因為Gentoo目前是在試驗階段,所以命令行加上--debug參數(shù)
  • 參數(shù)--email如果沒有在命令行加上,會在隨后彈出的對話框里提示你填寫
  • -w指定Web服務(wù)器網(wǎng)址內(nèi)容放置的目錄,請指定自己放置的目錄

生成的證書放在/etc/letsencrypt/live/[網(wǎng)站域名]

文件名 內(nèi)容
cert.pem 服務(wù)端證書
chain.pem 瀏覽器需要的所有證書但不包括服務(wù)端證書,比如根證書和中間證書
fullchain.pem 包括了cert.pem和chain.pem的內(nèi)容
privkey.pem 證書的私鑰

一般情況下fullchain.pemprivkey.pem就夠用了

Web服務(wù)端配置

采用的Nginx做的Web服務(wù)器,所以這里貼下我的服務(wù)端配置

因為同一個VPS上放置了多個站點,所以Nginx采用vhost的方式,將主域名以及子域名的Nginx配置文件單獨編寫,并放置在/etc/nginx/sites-available/下,如果哪個網(wǎng)站啟用,則在/etc/nginx/sites-enabled/下創(chuàng)建/etc/nginx/sites-available/對應(yīng)目錄的軟鏈接。這一套原本是Ubuntu發(fā)行版里面Nginx的默認(rèn)配置,個人覺得不錯,所以照搬到Gentoo里使用。

Nginx的主配置文件/etc/nginx/nginx.conf需要加入如下配置:

http {
    
    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

}

子域名vhost的配置,在/etc/nginx/sites-available/下創(chuàng)建文件subdomian并填入如下內(nèi)容

server {
    listen 443 ssl;
    server_name  subdomain.your_main_domain.com;
    # http://www.acunetix.com/blog/articles/configure-web-server-disclose-identity/
    server_tokens off;
    access_log /var/log/nginx/subdomain.your_main_domain.com.access_log;
    error_log /var/log/nginx/subdomain.your_main_domain.com.error_log;
    index index.html index.htm index.php;
    root /var/www/your_main_domain.com/subdomain;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
    ssl_prefer_server_ciphers on;
    ssl_certificate /etc/letsencrypt/live/subdomain.your_main_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/subdomain.your_main_domain.com/privkey.pem;
    ssl_session_timeout 5m;

    ssl_session_tickets      on;
    ssl_stapling             on;
    ssl_stapling_verify      on;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
    add_header X-Frame-Options deny;
    add_header X-Content-Type-Options nosniff;
    add_header               Content-Security-Policy "default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval' blob: https:; img-src data: https: http://ip.qgy18.com; style-src 'unsafe-inline' https:; child-src https:; connect-src 'self' https://translate.googleapis.com; frame-src https://disqus.com https://www.slideshare.net";

    # https://www.troyhunt.com/shhh-dont-let-your-response-headers/
    proxy_hide_header        Vary;
    fastcgi_hide_header      X-Powered-By;
    fastcgi_hide_header      X-Runtime;
    fastcgi_hide_header      X-Version;

    include php-fpm.conf;
}

server {
    server_name subdomain.your_main_domain.com;
    listen 80;
    server_tokens     off;
    access_log        /dev/null;
    location ^~ /.well-known/acme-challenge/ {
        alias         /home/name/.well-known/;
    try_files     $uri =404;
    }
    location / {
        rewrite       ^/(.*)$ https://subdomain.your_main_domain.com/$1 permanent;
    }
}
}

php-fpm.conf(全路徑 /etc/nginx/php-fpm.conf)的內(nèi)容:

location ~ \.php$ {
    # With php5-fpm:
    #fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    #fastcgi_param SCRIPT_FILENAME /var/www/$domain$subdomain$fastcgi_script_name;
    include fastcgi_params;
}

注意的問題

  • Gentoo的CONFIG_PROTECT問題。大家都知道,對于軟件的更新,除了軟件包自身的更新外,還需要配置文件的更新。如果一個軟件已經(jīng)安裝并運行,它已經(jīng)在使用配置文件(這個文件有可能用戶已經(jīng)定制過),那么當(dāng)這個軟件升級后,配置文件有可能發(fā)生更新(只要和正在使用的配置文件內(nèi)容不同就會更新),這個時候,機器上正在使用的配置文件和軟件升級后的配置文件就可能發(fā)生沖突(如果內(nèi)容不一致的話)。Gentoo定義了一個變量CONFIG_PROTECT(可以在/etc/portage/make.conf中定義)來負(fù)責(zé)保護本地的正在使用的配置文件內(nèi)容,如果配置文件的路徑寫在CONFIG_PROTECT中(多個配置用空格分開,路徑為全路徑),那么當(dāng)配置文件對應(yīng)的軟件升級后,這個配置文件不會被自動升級,而是在軟件升級完后系統(tǒng)會提示用戶配置文件有更新,或者用戶敲入etc-update命令后引導(dǎo)用戶解決配置文件沖突問題。參考官方文檔
  • 如果CONFIG_PROTECT="-*"表示取消配置文件保護
  • 如果想讓所有的配置文件都被保護,則應(yīng)該這樣寫CONFIG_PROTECT="*"

更新證書

Let’s Encrypt證書的默認(rèn)有效期只有90天,所以需要定時更新服務(wù)端的證書避免過期

一條命令更新所有服務(wù)端的證書

./letsencrypt-auto renew

添加為定時任務(wù), 編輯這個文件

sudo vi /etc/cron.monthly/letsencrypt_renew

添加如下內(nèi)容:

#!/bin/sh
/path/to/letsencrypt/letsencrypt-auto --debug renew > /var/log/letsencrypt/renew.log 2>&1

授予/etc/cron.monthly/letsencrypt_renew可執(zhí)行權(quán)限

sudo chmod a+x /etc/cron.monthly/letsencrypt_renew

撤銷證書

如果想收回(撤銷)頒發(fā)給服務(wù)端的證書,可以使用如下命令

./letsencrypt-auto revoke --cert-path /etc/letsencrypt/live/subdomain.your_main_domain.com/cert.pem

在線HTTPS配置檢查

可以使用Jerry Qu推薦的兩個在線HTTPS配置掃描服務(wù)來檢查你的網(wǎng)站HTTPS配置的問題,并根據(jù)建議做相應(yīng)的修復(fù)。


Qualys SSL Labs's SSL Server Test

HTTP Security Report

參考資料

Let’s Encrypt官網(wǎng)
Let's Encrypt,免費好用的 HTTPS 證書
LetsEncrypt SSL 證書簽發(fā)(Nginx)
聽說DNSpod也支持Let’s Encrypt了
免費SSL安全證書Let's Encrypt安裝使用教程(附Nginx/Apache配置)
免費SSL證書Let’s Encrypt安裝使用教程:Apache和Nginx配置SSL
LET’S ENCRYPT免費SSL證書申請過程
Ghost Blog啟用HTTPS使用LetsEncrypt SSL證書
Using Free SSL/TLS Certificates from Let’s Encrypt with NGINX

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容