正好年底了,有点闲钱整个nas玩玩。因为我之前折腾过轻服务器,选nas的时候就特别注重稳定性,所以买了极空间的Z2Pro。但是Z2Pro到手后,发现它的操作对新手特别友好,但对老手不太友好。有些打几行命令可以解决的事,他硬要你在GUI完成,包括这次配HTTPS也是,所以写篇文章记录下。
为什么要上HTTPS?
我有在公网直连WebDAV的需求,基于安全性的考量,是一定要上HTTPS的。
首先得了解什么是HTTP/HTTPS。HTTP是明文传输,在传输过程有被中间人攻击的可能性,即你传输的东西,会被别人看到。HTTPS是密文传输,在连接建立前通过多次握手确定密钥,后面进行加密传输。(这里就不细说了,有关这方面的区别,可以点击https://www.runoob.com/w3cnote/http-vs-https.html)
那再来看看WebDAV是什么。WebDAV是基于HTTP1.1的通信协议,通过暴露API让你完成对文件的操作。用过WebDAV的朋友都知道,在连接的时候,都会让你输入用户名和密码。那这个用户名和密码是怎么传到服务器的呢?其实,这里用的是HTTP的Basic Authorization进行鉴权。
在你输入用户名和密码后,浏览器/客户端会组成一个`${用户名}:${密码}`这样的字符串(得到a),对a进行Base64编码(得到b),在b前面添加’basic ‘,然后放在HTTP里的Authorization Header,再发到你的NAS。NAS得到你发的请求后,会先解析Authorization Header;如果用户名密码正确,进行下一步操作,否则返回403错误码。
注意,Base64不是加密算法,他只是一种编码方式,你拿一串编码后的Base64字符串,任何人都可以还原回来。刚刚也提到,HTTP是不加密传输的通信协议。所以如果你用HTTP请求并带上自己的账号密码,相当于你在互联网裸奔。如果别有用心的人在你请求服务器的路径中间“截胡”,即将你要发送的包内容记录下来,然后再原封不动地发给服务器(这里是你的nas),那他就肯定可以知道你的账号密码。
HTTPS就可以完美解决这个问题。“截胡”的人,他截取的内容都是经加密的、没有密钥就无法还原的,因此就避免了中间人攻击。当然你肯定想问,如果“截胡”的人知道你的加密密钥呢?emm…,这里可能性不大,涉及“鸡生蛋”的问题,有感兴趣的可以看看《计算机网络》这本书。
技术实现
已知,极空间会暴露5005端口用来提供WebDAV服务。
所以,我这里的方案是,公网暴露5006端口反向代理至极空间5006端口,极空间5006端口再反向代理至自身5005端口。
Nginx Proxy Manager
Nginx是一个很好的反向代理工具。但在代理WebDAV时有个坑:
- 它在反向代理时,会将一些没用的HTTP Header删掉
- 如果Header中带路径,它会自动忽略最后一个”/”
那经实践,这里就有一点点小问题了:
- 无法对文件重命名
- 无法移动文件
怎么解决呢?如果你用的是普通服务器,只需要给nginx添加headers-more-nginx-module模块,再重新编译nginx,然后再nginx配置文件补充这些缺失的header就行。
但不幸运的是,我买的是极空间,并不能直接编译nginx。(当然,有人说,你可以用docker啊,自己构建一个带模块的nginx。。。愿意折腾的同学可以试一试)
Nginx Proxy Manager其实是Nginx + CertBot + UI,所以Nginx有的问题,它肯定有。。解决方法,也很简单嘛,重新构建一个带模块的Nginx Proxy Manager镜像:
查看jc21/nginx-proxy-manager的Dockerfile,你会发现nginx是从jc21/nginx-full:certbot-node镜像获取的,因此我们也要构建带模块的jc21/nginx-full:certbot-node
看看jc21/nginx-full:certbot-node的Dockerfile,会通过./scripts/build-openrestry脚本去编译nginx
再看看这个脚本,豁然开朗。可以在这里加我们想要的插件了!
所以:
- 在build-openresty里,加入headers-more-nginx-module模块。
- 重新构建jc21/nginx-full:certbot-node
- 以jc21/nginx-full:certbot-node为父镜像,重新构建jc21/nginx-proxy-manager
- 发到公有docker仓库上(比如阿里云),让极空间下载镜像,然后跑起来!
这里有点繁琐,而且我在第一步就失败了,总是提示ubuntu缺少一些组件。
Apache
没用过,欢迎补充
Traefik
因为最近玩云原生比较多,想着既然用Nginx太复杂,那就试试Traefik?
从官网可以看到,Traefik是建议通过Docker Compose部署的,但极空间不支持嘛,所以用Docker CLI也行。。
从官网也可以看到,Traefik推荐给每个Docker容器配动态参数,然后Traefik去读这些参数,给这些Docker容器做反向代理。但极空间又不支持嘛,所以用文件配置也行。。
讲了这么多,怎么做呢?
拉取镜像
# 对应Docker命令
docker pull traefik:latest
创建/配置容器
用上面的镜像创建容器:
上面的ALICLOUD_ACCESS_KEY / ALICLOUD_SECRET_KEY填你在阿里云的apiKey信息。这里的apiKey,需要带上所有域名权限,因为traefik在获取ssl证书时,会在你域名的dns里增加一条记录,用来鉴权。
如果没有域名的小伙伴,可以去阿里云搞一个便宜的域名,一年也就十几块钱。
# 对应的Docker命令
docker run traefik -v ... -p ... -e ... -d
然后别急。整理下,这里挂载的Volume为:
- /Docker/traefik/config (文件夹,放文件动态配置)
- /Docker/traefik/certs (文件夹,放Traefik自动申请的证书)
- /Docker/traefik/traefik.toml (文件,traefik配置)
- /Docker/traefik/acme.json (文件,证书请求信息)
这里打住,先不要启动容器
配置Traefik
- 在挂在目录下创建traefik.toml文件,内容为:(里面需要替换你的邮箱)
[global]
checkNewVersion = true
sendAnonymousUsage = true
[entryPoints]
[entryPoints.webdav]
address = ":5006"
[log]
level = "DEBUG"
[api]
[ping]
[certificatesresolvers.default.acme]
email = "你的邮箱"
storage = "/letsencrypt/acme.json"
dnschallenge.provider = "alidns"
[providers.file]
directory = "/etc/traefik/config"
watch = true
上面配置了什么呢?
- 打开版本检查/发送匿名信息(默认的)
- 重点:新加一个入口(entrypoints),监听端口号5006
- log等级为debug(方便排查错误)
- 打开api访问(默认)
- 打开ping(默认)
- 证书信息(在这里填入你的证书请求信息,包括邮箱,域名服务商)
- 打开文件provider(默认的provider是docker,这里我关了,即监听容器内目录/etc/traefik/config下所有配置文件的变化)
2. 在挂载目录/Docker/traefik/config中,新加一个webdav.yml文件(随意起名),里面填入:(注意替换你的域名和和NAS局域网ip)
http:
routers:
webdav:
entrypoints:
- webdav
rule: Host(`你的域名`)
tls:
certResolver: default
service: svc_webdav
services:
svc_webdav:
loadBalancer:
servers:
- url: "http://NAS局域网ip:5005"
3. 创建一个空的acme.json,移动到/Docker/traefik/里
4. 启动traefik容器
到这里就配置成功了。你以为结束了吗?别急,这里还有坑~
设置acme.json权限
我们ssh到容器内部(小坑:命令用/bin/sh)
# 对应Docker命令
docker exec -u root -it traefik sh
找到容器内部,刚刚挂在的acme.json文件,权限设置为600(默认权限是777,traefik会报错;极空间也不支持改变文件权限,所以只能走弯路啦~)
然后关闭窗口,重启容器
验证
在游览器输入https://域名:5006,看看HTTPS是否正常呢?
在ssl证书过期时,traefik会自动更新你的证书哦~
然后试一下外网访问WebDAV时,创建文件、移动文件、文件重命名是否正常,我这里是一切正常的哦~
总结
Traefik是一个很好用的反向代理工具~
完全按照LZ的来还是不行诶,是我太菜了