给HTTP服务添加SSL证书,防止中间人攻击——使用acme.sh申请证书并配置HTTPS访问
基于网络的普及和网速的提升,我们普通用户也可以搭建自己的HTTP服务并开放到公网中方便我们随时随地访问,如开源的智能家居系统Home Assistant、支持WebDAV协议的网盘、网络摄像机等。不过HTTP协议是使用明文传输方式来传输信息的,当你访问只支持HTTP协议的网站,在经过路由器、宽带接入商等中间环节时,搜索的关键字、账号密码等都是可见的,这些信息很容易被截获从而造成重要数据的泄露。这样就产生了由SSL + HTTP协议构建的可进行加密传输、身份认证的网络协议:HTTPS协议。在HTTPS协议下传输数据,客户端会将数据加密后发送到服务器,服务器解密后获得数据,反之亦然。在此过程中,数据通过密钥进行加密,这样即使中间环节劫持到内容也会因没有密钥无法破解。
下面我们就为自己的HTTP服务配置SSL证书并使服务可以从公网访问。
一、申请域名并绑定自己的公网IP地址
目前三大运营商基本都支持IPv6了,只要你有一个支持IPv6的路由器就可以为你的上网设备分配到公网IPv6地址,不过这个地址是会变动的,我们需要实时将变动后的IP地址绑定到域名上,接下来我以dynv6的使用为例,申请域名并配置DDNS。
1.申请域名
到Free dynamic DNS for IPv6 (dynv6.com)这个网站使用邮箱注册一下,在经过邮箱验证后就可以创建自己的域名了,如下图:
在Name后的文本框中给域名起个名字,点击“Create Zone”按钮,记录下图红框中的域名和token
2.绑定域名和IP地址
下载脚本dynv6.sh
使用WinSCP或SecureCRT等工具将脚本上传到需要绑定的设备中(我这里使用Armbian的root用户做演示,将脚本上传至/usr/local/bin目录)
赋予脚本执行权限
cd /usr/local/bin chmod u+x dynv6.sh
编辑定时任务
crontab -e
添加以下内容
* * * * * token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /usr/local/bin/dynv6.sh v6test.dns.army
等待一分钟后,查看当前目录中是否生成.dynv6.addr6文件(使用ls -la命令查看隐藏文件)
查看文件内容
cat .dynv6.addr6
使用以下命令解析域名v6test.dns.army的IP地址
nslookup v6test.dns.army 8.8.8.8
解析出来的IPv6地址与.dynv6.addr6中的一致则动态域名服务配置成功
3.配置泛域名
我们在自己创建的域名下切换到Records标签,添加一条CNAME记录,如下图:
Name中填入“*”后点保存
追加:最近发现在给dynv6域名添加CNAME记录时,Name中填写“*”保存后过一会儿此条CNAME记录就会被删除,导致子域名解析失败。可以分别添加子域名的CNAME记录,比如我在Caddy中配置的子域名有file、hass、docker、op这几个,那么就在Records标签中按照下图添加CNAME即可
二、安装acme.sh并生成证书
1.安装acme.sh
下载acme.sh
wget https://github.com/acmesh-official/acme.sh/archive/master.tar.gz
解压
tar -zxvf master.tar.gz
进入解压后的目录
cd acme.sh-master/
安装到指定目录并配置邮箱地址
./acme.sh --install \ --home /usr/local/acme.sh \ --accountemail xxxxxx@xx.com
安装成功后可以删除下载的压缩包和解压目录
cd .. && rm -rf acme.sh-master/ && rm -rf master.tar.gz
进入安装目录
cd /usr/local/acme.sh
配置acme自动更新
./acme.sh --home ./ --upgrade --auto-upgrade
2.生成域名对应的证书
设置dynv6的HTTP TOKEN
export DYNV6_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
生成证书
./acme.sh --home ./ --issue --dns dns_dynv6 -d v6test.dns.army -d *.v6test.dns.army
三、通过Caddy启用HTTPS
1.下载Caddy
创建Caddy存放目录
mkdir -p /usr/local/caddy
到Caddy官网(Download Caddy (caddyserver.com))下载对应平台的二进制文件(我使用的是Armbian 64位系统,平台选择Linux Arm64),选中带有WebDAV插件的可执行程序,点击下载
将下载好的Caddy程序上传到/usr/local/caddy目录中
修改程序名称为caddy
cd /usr/local/caddy mv caddy_linux_arm64_custom caddy
赋予执行权限
chmod u+x caddy
2.配置Caddyfile
创建SSL证书存放目录
mkdir -p /usr/local/caddy/ssl
在/usr/local/caddy目录创建Caddyfile文件
vim Caddyfile
填写配置内容
{ # 指定http端口为85 http_port 85 order webdav before file_server } # WebDAV服务,子域名设置为file,指定https端口为8443 file.v6test.dns.army:8443 { # 设置/mnt/XiaoMi为可以被访问的目录,可自行修改为想要访问的目录 root * /mnt/XiaoMi encode gzip # 在Caddy目录中使用以下命令生成密码,此处以12345为例 # ./caddy hash-password --plaintext 12345 basicauth { test JDJhJDE0JFo4TkxBUjQ1YTdZVXdQQ3BvUjA2Z09POTFSVkwzRnZLalh4QkY3OW14Rks3Q3pkRzkwWDdH } # 指定证书文件存放位置,绝对路径为/usr/local/caddy/ssl,此处使用Caddyfile文件所在目录(/usr/local/caddy)的相对路径 tls ssl/full_chain.pem ssl/private.key route { rewrite /webdav /webdav/ webdav /webdav/* { # 访问WebDAV服务的前缀 prefix /webdav } # HTTP文件服务,可以在浏览器中查看下载文件 file_server browse } } # 代理HomeAssistant hass.v6test.dns.army:8443 { encode gzip tls ssl/full_chain.pem ssl/private.key reverse_proxy localhost:8123 } # 代理Portainer docker.v6test.dns.army:8443 { encode gzip tls ssl/full_chain.pem ssl/private.key reverse_proxy localhost:9001 } # 代理OpenWrt op.v6test.dns.army:8443 { encode gzip tls ssl/full_chain.pem ssl/private.key reverse_proxy 192.168.2.202 }
3.使用acme.sh安装证书
进入acme.sh目录
cd /usr/local/acme.sh
安装证书到指定目录并重新载入caddy配置
./acme.sh --home ./ --install-cert -d v6test.dns.army \ --key-file /usr/local/caddy/ssl/private.key \ --fullchain-file /usr/local/caddy/ssl/full_chain.pem \ --reloadcmd "cd /usr/local/caddy && killall -9 caddy; nohup ./caddy run > /dev/null 2>&1 &"
进入证书存放目录
cd /usr/local/caddy/ssl
可以看到已经生成full_chain.pem和private.key两个文件
4.验证配置文件是否有效
回到caddy目录
cd /usr/local/caddy
测试配置文件是否正确
./caddy validate
没有错误信息则证明配置文件没有问题
5.启动Caddy
启动Caddy
./caddy run
测试配置的WebDAV和反向代理没有问题的话可以后台启动
./caddy start
设置开机时自动运行Caddy
vim /etc/rc.local
在exit 0上面添加以下命令
cd /usr/local/caddy nohup ./caddy run > /dev/null 2>&1 &
四、开放公网IPv6访问端口
这里分别介绍Padavan和OpenWrt开放IPv6访问端口的方法。
1.Padavan开启IPv6外网访问端口
(1)开启路由器自身端口
ip6tables -A INPUT -p tcp --dport 85 -j ACCEPT ip6tables -A OUTPUT -p tcp --sport 85 -j ACCEPT ip6tables -A INPUT -p tcp --dport 8443 -j ACCEPT ip6tables -A OUTPUT -p tcp --sport 8443 -j ACCEPT
(2)开启局域网其他设备端口
ip6tables -A FORWARD -p tcp --dport 85 -j ACCEPT ip6tables -A FORWARD -p tcp --dport 8443 -j ACCEPT
(3)开机自动开放端口
在“高级设置”->“自定义设置”->“脚本”->“在防火墙规则启动后执行:”最后添加以下内容
# 开启路由器自身端口
ip6tables -A INPUT -p tcp --dport 85 -j ACCEPT ip6tables -A OUTPUT -p tcp --sport 85 -j ACCEPT ip6tables -A INPUT -p tcp --dport 8443 -j ACCEPT ip6tables -A OUTPUT -p tcp --sport 8443 -j ACCEPT
或
# 开启局域网其他设备端口
ip6tables -A FORWARD -p tcp --dport 85 -j ACCEPT ip6tables -A FORWARD -p tcp --dport 8443 -j ACCEPT
点击最下面的“应用本页面设置”
2.OpenWrt开启IPv6外网访问端口
(1)开启路由器自身端口
ip6tables -I INPUT -p tcp --dport 85 -j ACCEPT ip6tables -I OUTPUT -p tcp --sport 85 -j ACCEPT ip6tables -I INPUT -p tcp --dport 8443 -j ACCEPT ip6tables -I OUTPUT -p tcp --sport 8443 -j ACCEPT
(2)开启局域网其他设备端口
ip6tables -I FORWARD -p tcp --dport 85 -j ACCEPT ip6tables -I FORWARD -p tcp --dport 8443 -j ACCEPT
(3)开机自动开放端口
vim /etc/rc.local
在exit 0上面添加
# 开启路由器自身端口 ip6tables -I INPUT -p tcp --dport 85 -j ACCEPT ip6tables -I OUTPUT -p tcp --sport 85 -j ACCEPT ip6tables -I INPUT -p tcp --dport 8443 -j ACCEPT ip6tables -I OUTPUT -p tcp --sport 8443 -j ACCEPT
或
# 开启局域网其他设备端口 ip6tables -I FORWARD -p tcp --dport 85 -j ACCEPT ip6tables -I FORWARD -p tcp --dport 8443 -j ACCEPT
保存退出
四、使用Caddy配置的域名加端口访问HTTPS服务
我们使用docker.v6test.dns.army:85这个地址访问Portainer,可以看到地址栏网址会自动跳转到https://docker.v6test.dns.army:8443,而且地址栏前面会显示“连接安全” 的小锁,如下图:
这样我们的HTTPS服务就配置完成了。