之前一直想为博客添加TLS,一直懒得搞,今天也总算是搞完了,顺便学习一下Nginx。

1、引言

由于博客一直没有HTTPS,这样会导致在公网环境下登录博客后台的密码泄露,所以一直想给博客加上TLS。但是涉及到Docker容器,事情就变得复杂了一点点,有两种选择,第一种就是在Docker容器里面安装中间件,即Apache、Nginx等,但是由于博客本身并没有使用到这两个中间件,所以需要反向代理,自然选择了Nginx。第二种是在物理机上安装Nginx,然后反向代理Docker容器。为了使容器和主机之间的逻辑关系更加清晰,这里我选择了第二种,即通过主机的Nginx控制所有Docker容器。

2、Nginx使用

Nginx是一款高性能开源的Web服务器和反向代理服务器,擅长处理大量并发连接,支持静态内容服务、负载均衡和HTTPS加密,因其高效、轻量和稳定,被广泛应用于大型网站和互联网服务中。

首先就是Nginx的目录,其中有几个关键文件夹:
/etc/nginx/:nginx主目录
/var/www/html/:默认的网页根目录,存放静态网页文件
/etc/nginx/nginx.conf:主配置文件,定义全局配置和包含其他配置文件,如ssl证书位置等
/etc/nginx/site-available/:存储nginx的配置文件,用户可以自定义,不一定生效
/etc/nginx/site-enable/:存储启用的配置文件,这里的文件是site-available里面文件的软链接,这些文件被包含到nginx.conf里面生效
/etc/nginx/conf.d/:存放额外的配置文件,通常以.conf结尾,与site-enable一样自动在nginx.conf里面加载
/var/log/nginx/:存放Nginx的访问日志和错误日志文件

修改配置文件后用

nginx -t

检测语法错误,随后用

systemctl reload nginx 或 nginx -s reload

重载nginx生效。

3、配置文件

在使用时,我们把ssl配置信息放在主配置文件中,即nginx.conf中,这个网上有,而且比较统一,所以不做演示。然后便是针对不同站点的反向代理写不同的配置文件,并存放于site-available文件夹中,使用时,将该配置文件用ln -s命令创建软链接到site-enable中即可。当然这是比较规范化的做法,所以有些许麻烦。下面展示一些配置文件细节。


#将所有访问shl528.cn:80的请求转移至https://shl528.cn:443
server {
    listen 80;
    server_name shl528.cn;
    #return 301 https://shl528.cn;
    return 301 https://$host$request_uri;
}

#将所有访问shl528.cn:443的请求转移至http://127.0.0.1:8080
server {
    listen 443 ssl;
    server_name shl528.cn;
    location / {
    proxy_pass http://127.0.0.1:8080;
    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;
}

这份配置文件首先实现了用户访问80端口时,也就是http服务,会跳转至提供加密的443端口。也就是在服务端实现了强制用户访问https网站的功能;其次,为了本地开放的8080端口其实是http服务,也就是docker容器映射出来的在本地的http服务,这相当于实现了通过Nginx对Docker容器添加TLS的功能。

4、Nginx反向代理子域名

假设场景:你的主域名下开了一个17788端口的服务,每次访问你都要输入完整的域名和端口,这样显得很麻烦,所以你打算用子域名去代理这个端口的服务。

解决方案:首先,在域名购买的平台添加子域名解析,之后在服务器中,填写对应的配置文件,如下所示。

server {
listen 443;
server_name frp.shl528.cn;

location / {
    proxy_pass http://127.0.0.1:17788;
    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;
    }
}

这里有个问题,为什么不监听80端口呢?

如果一个网站开放了HTTPS服务,并且之前本地浏览过,浏览器一般会强制使用443端口访问网站,而不会访问80端口,手动修改也无济于事,如果想用80端口访问,可以使用curl工具。这种情况通常由浏览器本地缓存造成的,这便会导致我们在浏览器中,输入http://frp.shl528.cn:80后,浏览器会访问https://frp.shl528.cn:443,如下图所示。这并不会触发Nginx中对frp.shl528.cn:80的监听,具体可以用Wireshark抓包查看。

image.png

当然,这里可以换一个别的子域名,浏览器默认还是会访问子域名的80端口的,例如aaa.shl528.cn,这样便可以解决浏览器本地缓存的问题。为了避免这些乱七八糟的问题,这里监听443端口。此外,由于443端口配置了TLS加密,所以我们的网站顺理成章的用上了TLS加密,只不过显示证书不安全,因为证书是主域名的证书。

另外插一嘴,如果我们设置了域名泛解析,所有子域名都会指向IP:80这个服务,例如用curl访问sdkfjlaskjf.shl528.cn,则会返回301重定向,但是我们并没有设置匹配sdkfjlaskjf.shl528.cn:80的301重定向啊,Nginx 的规则是这样的:当请求的Host没有匹配到任何server_name时,它会选择该listen端口下第一个出现的server块来处理这个请求,这个“第一个”是指:在配置文件中出现的顺序。如此,则会自动跳转至https://sdkfjlaskjf.shl528.cn:443

配置完这些东西后,记得关闭主域名上的服务端口哦,改为仅本地可访问,避免了一个服务的多个访问方式。

5、Nginx的日志机制

Nginx日志中包含访问的ip,http头,user-agent,时间字段,默认保存地址为/var/log/nginx/access.log

Nginx日志只会记录HTTP请求,若通过某个url将HTTP升级为WebSocket,则日志里只会有一条请求。

此外,由于日志轮询机制不归Nginx管,由logrotate程序管理,所以修改文集后还需要执行logrotate -f /etc/logrotate.d/nginx命令来使其生效。

标签: Nginx, Docker

添加新评论