1.理论基础
基本思想
HTTP 和 HTTPS 的主要区别在于是否对信息进行了加密。HTTP 服务是基于 TCP 的明文传输,无法保障数据安全。在数据加密传输中,加密方式可分为对称加密和非对称加密两种。对称加密即使用一个密钥对数据进行加密,再将密钥与数据同时传输,接收端用相同的密钥解密;很显然这样的加密方式并不能保障数据安全。而非对称加密可以解决这个问题,非对称加密在密钥生成时会产生一对密钥——即公钥和私钥,公钥可以在网络上传输,用以给数据加密;而私钥必须妥善保管,尽可能避免泄露,用以给数据解密。显而易见,如果公钥和私钥是唯一对应的关系那么数据的安全性将大打折扣,只需要知道算法就可以推算出私钥;因此,公私钥的算法往往可以产生相当庞大数量的密钥对,这样即使从网络上获知公钥的信息也无法推算出私钥。HTTPS 服务就是依据非对称加密在 HTTP 的基础上进行 SSL/TLS 加密的加密传输服务。
中间人攻击
但非对称加密并非绝对安全。首先,非对称加密的公钥是暴露在网络中的,这就给了有心之人可乘之机。

图 1
如图 1 所示,面对非对称加密的数据,可以以中间人的方式劫持公钥和网络流量(即中间人伪装为用户面向服务器),再由中间人生成新的密钥对,中间人伪装成服务器将新的密钥下发给用户,这样用户传输给服务器的加密信息就彻底暴露在中间人面前,中间人可以在传输过程中随意对数据进行修改,包括但不限于:窃取隐私信息(如密码、保密资料等)、篡改通讯内容、植入木马病毒等。
面对绝大多数中间人攻击,互联网衍生出一套完整的防御体系——即使用可信的第三方对数据做认证,也就是 CA 认证。CA 认证服务器会产生一对新的公钥和私钥,私钥会以某种安全途径送达服务器,公钥依然是可以暴露在网络中。相较于无 CA 服务器认证的情况,有 CA 认证的服务器在发送数据时会同时用 CA 证书的私钥加密产生一个数字签名,而公钥则用于验证数字签名。由于数字签名是私钥加密的,中间人无法获取私钥,也就没办法产生可信的数字签名,中间人攻击也因此而失效。同时,CA 证书也存在有效期,有效降低了中间人攻击的风险。
但这里依然存在一个问题:如果中间人可以伪造有效的 CA 证书怎么办?就目前而言,面对这样的攻击是很难有办法的。一般来说,绝大部分的中间人攻击都不具备这样的条件,但是对于庞大的运作体系来说伪造可信的 CA 证书轻而易举。CA 证书的可信度往往由用户的浏览器或系统与相关机构达成相应的合作或共识之后做出相应的修改;但对于可以强制修改用户浏览器或系统相关内容的庞然大物来说,伪造 CA 证书只需要做出相关协调即可。比如 GFW 体系中就存在高度完善的中间人攻击服务器,下面的链接中有对 GFW 泄露信息的详细说明
反向代理
对于经常用梯子的人,代理一定不陌生;相应的,反向代理也是类似的原理,即使用代理服务器将数据进行转发传递给数据目标。对于用户而言,代理不仅可以帮助他们绕开一些限制将数据顺利送达目标服务器,还可以向服务器隐瞒身份使其无法追查数据来源;相应的,对服务端而言,代理也可以帮助服务端绕开一些限制,同时保护其上的数据安全,使访问者无法顺利追查服务端,这一行为被称为反向代理。想要将服务端已有的 HTTP 服务转为 HTTPS 服务,反向代理就必不可少;其中一个常用方法是使用服务器的 nginx 将已有的 HTTP 服务反向代理到其他端口,配合证书和私钥,可以将原有的 HTTP 服务代理到其他端口成为 HTTPS 服务。当然 apache 等也是提供反向代理服务的,可以根据需求选择。
2.准备工作
根据理论基础中的内容,我们不难得知我们需要做好以下准备:
域名
域名的获取方式有很多种,根据付费与否可以分为免费域名和付费域名两种。一般来说,免费域名几乎不可能备案(备案是仅限于中国大陆的独特管理机制,详情参见链接文章
下面推荐一个比较好用的免费域名网站:,这个网站注册后有一个免费域名的申领资格,而且域名可以延伸二级域名、三级域名等,还可以托管至 cloudflare,但是需要 IP 纯净度足够高才能成功申领,可以用梯子上冷门的节点尝试。
下面是 IP 纯净度检测的网站:,在网页下面会显示你当前登录网址的 IP,将其复制到上面的检测框检测即可。
CA证书
同样的,CA 证书也有免费和付费证书两种,两种证书都需要验证域名的所有权,主流的验证方式主要有 DNS 记录验证、webroot 验证和文件验证,推荐使用 DNS 验证。获取证书和私钥后将其放在服务器的特定位置,并限制其权限,debian 系统的指令如下:
sudo chmod 644 /path to your crt/example.com.crt # 证书可读
sudo chmod 600 /path to your key/example.com.key # 私钥仅 root 可读写免费证书可以用 Let's Encrypt 或者其衍生 certbot 进行申请和定期续订(每次有效期 90 天)。certbot 申请泛域名证书的指令如下:
sudo certbot certonly \
--manual \
--preferred-challenges=dns \
--server https://acme-v02.api.letsencrypt.org/directory \
-d *.example.com \
-d example.com其中最后一句是给域名本身而非二级域名申请证书。下面的官方网址中介绍了如何安装和自动续订证书的方法:
上面的泛域名证书申请需要验证所有权,该指令使用手动 DNS 记录的方式验证,验证前需要将其他同类型的 TXT 记录删除,并一直保留 certbot 给出的 TXT 记录(用于后续自动续订的所有权验证)
nginx
Debian 安装 nginx 的方法如下:
sudo apt update
sudo apt upgrade -y
sudo apt install nginx3.nginx配置
nginx 的配置文件一般在 /etc/nginx 目录下,但是我并不建议直接修改 /etc/nginx/nginx.conf;我推荐在 /etc/nginx/conf.d 目录中新建虚拟主机配置文件(.conf 文件),既不干扰已有配置,也能保证及时定位、解决问题。下面是虚拟主机配置模板:
server {
listen https_port ssl;
server_name yourdomain; # 替换为你的域名
client_max_body_size 2048m; # 根据需求调整大小,这直接决定了网页可以传输数据的最大上限,默认1MB
# SSL证书配置
ssl_certificate /path to your crt/example.com.crt; # 替换为证书位置
ssl_certificate_key /path to your key/example.com.key; # 替换为私钥位置
ssl_protocols TLSv1.2 TLSv1.3; # 支持的TLS协议
ssl_ciphers HIGH:!aNULL:!MD5;
# 反向代理到HTTP端口
location / {
proxy_pass http://localhost:port; # 本地端口,即原HTTP服务端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# 强制HTTP跳转到HTTPS(301重定向)
server {
listen http_port; # 替换为想要监听的HTTP端口
server_name yourdomain; # 替换为你的域名
return 301 https://$host$request_uri;
}增加 301 重定向的原因是大部分浏览器在使用中只输入域名会默认使用 HTTP 协议访问,此时就会产生 403 报错,增加一层 301 重定向即可直接解决问题。另外的方案是在 cloudflare 中托管域名,并将域名通过 cloudflare 代理解析到服务器,再添加重定向的规则,不仅麻烦,而且不一定能生效,因此直接在 nginx 端重定向即可解决问题。
将.conf 文件保存后运行以下命令:
sudo nginx -t # 检查nginx配置文件是否存在语法错误
sudo systemctl reload nginx # 服务重载或者使用第三行命令进行重启
sudo systemctl restart nginx # 重启nginx服务此时已经成功应用 nginx 代理服务,有公网 IP 且域名已经解析到服务器的可以直接通过.conf 文件中的域名访问相应的服务,没有公网 IP 的需要经过穿透服务才可以正常使用。
4.frp内网穿透(可选)
frp 穿透服务要求有公网服务器才可以使用,也可以选择购买或白嫖其他人搭建的 frp 服务,我使用的是 chmlfrp 的 frp 服务,有免费也有付费服务,对于轻量化的 Web 来说,境外免费服务也是足够使用的。
frp 服务主要有四种数据穿透,分别是:TCP、UDP、HTTP 和 HTTPS,对于可以操作服务端的站长来说,通过对服务端添加 nginx 反代也可以直接将 HTTP 服务转为 HTTPS 服务,其数据流向如图 2 所示:

图 2
在这种方式中,web 服务的搭建者需要自己再购买专门的有公网的服务器来搭建 frp 转发业务,nginx 由 frp 服务器接管,数据的 SSL/TLS 加密和解包都在该服务器中完成,真正提供 Web 服务的服务器与 frp 服务器之间的通信仍然是 frp 转发的 TCP 数据,走的是 HTTP 协议,为了保证安全,传输过程中还需要对 frp 数据加密(frp 本身就提供数据加密)。
另外的方法则是走 frp 服务的 HTTPS 透传,这样即使买(或者白嫖)别人服务也可以正常(只要服务提供 HTTPS 透传)传输 HTTPS 加密数据,其数据流向如图 3 所示:

图 3
这里就需要用到 3 中的 nginx 配置,在 web 服务器本地就将 HTTP 服务代理为 HTTPS 服务,并将其利用 HTTPS 透传暴露在公网中。
但这样会遇到一个问题:nginx 中的 301 重定向此时就无效了。聪明的你肯定想到了将 nginx 中 301 重定向的端口也透传出来,HTTP 透传和 HTTPS 透传共用一个域名,即可完成 301 重定向。
5.gitlab的反向代理(可选)
与其他服务不同的是,gitlab 这类服务是内置 nginx 的,也就是说,他们可以自己做反向代理提供 https 服务而不需要额外的服务干预,可以在 /etc/gitlab/gitlab.rb 中找到以下语句或直接将其添加至 gitlab.rb 文件
external_url ‘your domain’ # 替换为你的域名
nginx['listen_port'] = 443 # https服务监听端口
nginx['enable'] = true
nginx['redirect_http_to_https'] = true # 开启重定向
nginx['redirect_http_to_https_port'] = 80 # 重定向监听端口
nginx['ssl_certificate'] = "/path to your crt/example.com.crt" # 证书
nginx['ssl_certificate_key'] = "/path to your key/example.com.key" # 私钥之后执行以下命令重载 gitlab 配置文件,并重启 gitlab 服务
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart之后按需将域名解析到服务器或 frp 服务器(还需建立 HTTPS 透传和 HTTP 透传)即可正常访问。
默认评论
Halo系统提供的评论