——— 现代Web架构中主流安全和性能提升技术🌞
一、反向代理和nginx软件
1. 正向代理:帮客户端打掩护的“跑腿小哥”
场景:你想买杯奶茶,但奶茶店在马路对面,而你的腿受伤了没法过去。这时你叫了个跑腿小哥帮你买,奶茶店老板只会看到小哥,不知道你的存在。
原理:
- 作用对象:代理的是客户端(比如你的手机/电脑)。
- 隐藏谁:隐藏的是你的身份(奶茶店老板不知道谁要喝奶茶)。
- 典型例子:
- 科学上网(VPN):比如你通过代理访问国外网站,网站看到的是代理的IP,而不是你的真实IP。
- 公司内网限制:员工用公司代理访问外网,老板可以监控员工上网行为。
一句话总结:正向代理是帮用户干活的中间人,用户需要主动找它帮忙(比如设置代理服务器)。
2. 反向代理:帮服务器挡枪的“饭店前台”
场景:你去饭店吃饭,前台服务员(反向代理)接待你,你只管点菜,但菜是后厨不同的厨师做的。你不需要知道后厨有几个人、谁炒的菜,服务员会帮你搞定一切。
原理:
- 作用对象:代理的是服务器(比如网站的后台)。
- 隐藏谁:隐藏的是服务器身份(你访问的是淘宝,但背后可能有1000台服务器在干活)。
- 典型例子:
- 网站负载均衡:比如淘宝用反向代理把用户请求分发给不同的服务器,避免某台服务器被挤爆。
- 隐藏服务器IP:黑客攻击时只能打到代理服务器,伤不到真正的服务器。
一句话总结:反向代理是帮服务器干活的挡箭牌,用户根本感觉不到它的存在(你访问的还是“淘宝.com”)。
3. nginx软件
作为反向代理的软件的翘楚,nginx因其高并发、模块化和完全开源等特性被各大企业广泛使用;我们想知道nginx到底是个啥,我们只需要体验下它的部署和使用就清楚了。
测试平台:linux
首先就是找一个靠谱的docker-compose.yml(用于docker容器的一键部署)文件了,我用的配置如下
#version: '3.8' # 推荐使用较新的版本
services:
nginx:
image: nginx:latest
container_name: nginx # 容器名
ports:
- "80:80"
- "443:443" # HTTPS端口映射,这里打开,以便你后面用https
volumes:
- /root/nginx/conf.d:/etc/nginx/conf.d # 配置文件目录
- /root/nginx/ssl:/etc/nginx/ssl # SSL证书目录
- /root/nginx/logs:/var/log/nginx # 日志目录
- /etc/localtime:/etc/localtime:ro # 同步本地时间
- /etc/timezone:/etc/timezone:ro # 同步本地时区
networks:
- my-network # 自定义网络
restart: unless-stopped # 推荐添加容器重启策略
privileged: false # 安全建议:避免赋予特权
networks:
my-network: # 显式声明网络配置
driver: bridge
attachable: true # 允许其他容器加入
然后bash/zsh中输入
docker compose up -d
查看容器状态看服务是否启用成功。
上述我们挂在了nginx的配置文件到/root/nginx/conf.d
目录,这个也是部署了nginx服务后唯一需要控制和修改的地方,这也是为什么nginx软件非常容易使用的原因,我们只需要关心配置中那些参数的意义就可以了。
我们可以
vim /root/nginx/conf.d/default.conf
其默认配置如下
# 工作进程的数量
worker_processes 1;
events {
worker_connections 1024; # 每个工作进程连接数
}
http {
include mime.types;
default_type application/octet-stream;
# 日志格式
log_format access '$remote_addr - $remote_user [$time_local] $host "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$clientip"';
access_log /srv/log/nginx/access.log access; # 日志输出目录
gzip on;
sendfile on;
# 链接超时时间,自动断开
keepalive_timeout 60;
# 虚拟主机
server {
listen 8080;
server_name localhost; # 浏览器访问域名
charset utf-8;
access_log logs/localhost.access.log access;
# 路由
location / {
root www; # 访问根目录
index index.html index.htm; # 入口文件
}
}
# 引入其他的配置文件
include servers/*;
}
上述配置的关键是从22行开始,当用户访问localhost的8080端口的时候,nginx会将访问入口指向静态文件index.html
,这里用户并不知道其访问的内容来自于哪里,只知道访问的是localhost:8080,这就是反向代理。
二、https安全传输协议
这个不必多说,就是一种端对端的加密技术,现在广泛使用,浏览器访问时不是https的协议都通不过安全检测。
nginx的https配置
我们这里要讲的是怎么在nginx部署这个安全协议让你的网站可以被相对安全地访问,假如你已经有自己的域名,我这里假设一个hello.com
, 我这里给出一个nginx的简单配置
# 强制 HTTP 跳转 HTTPS
server {
listen 80;
server_name hello.com;
return 301 https://$host$request_uri;
}
# HTTPS 服务配置
server {
listen 443 ssl;
server_name hello.com;
# SSL 证书路径
ssl_certificate /etc/nginx/ssl/fullchain.pem; # 公钥证书文件
ssl_certificate_key /etc/nginx/ssl/key.pem; # 私钥证书文件
ssl_protocols TLSv1.2 TLSv1.3; # 加密协议
ssl_ciphers HIGH:!aNULL:!MD5;
# 修改后配置(根路径代理)
location / {
proxy_pass http://hello.com:8080/;
proxy_set_header Host $host; # 请求头,标识用户信息,浏览器版本等
proxy_set_header X-Real-IP $remote_addr; # 主要做访问控制
}
}
关键的还是从第8行开始看,nginx服务监听443端口,当用户访问hello.com的443端口时,nginx将请求转发到http://hello.com:8080/
这个真实的后端地址,这样用户以为自己访问的是hello.com,从而实现了反向代理。
这里需要简单提一下,443这个端口是https服务的默认端口,也就是你访问https://hello.com
实际访问的是https://hello.com:443
,只不过443被默认隐藏了;
免费证书自动更新
可能你注意到了,14行和15行指定了两个文件的路径,这两个文件是实现https加密协议的关键,简单地说就是提供了密钥对;因为我们用docker部署的nginx服务,所以这两个路径是指的容器内部的路径,如果对应到宿主机路径应该是
/root/nginx/ssl/fullchain.pem; # 公钥证书文件
/root/nginx/ssl/key.pem; # 私钥证书文件
这两个证书哪里来呢,这里我们不介绍阿里云或者腾讯云提供的免费证书,我们只介绍可以免费自动更新的证书,以前我会每隔几个月去服务商下载免费的证书替换,这个太麻烦了,一不小心就忘了,所以需要可以自动更新的证书。
免费证书工具挺多,有Let’s Encrypt,ZeroSSL等,这里推荐使用证书自动管理脚本acme,我们只需要
yum install git -y
git clone https://github.com/acmesh-official/acme.sh.git
注册邮箱
acme.sh/acme.sh --register-account -m "test@example.com"
由于这个服务要依赖于域名服务商的解析服务,所以需要添加
# 阿里云
export Ali_Key="LTAI5tDBRV2fxxxxxxxxxxxx"
export Ali_Secret="0tLWTpemxLCkm1oxxxxxxxxxxxxxxx"
# DNSPod
export DP_Id='220xxx'
export DP_Key='815607ebc4ba6006xxxxxxxxxxxxxxxx'
最后生成一下证书即可
# 阿里云
/root/acme.sh/acme.sh --issue --dns dns_ali -d hello.com --force --cert-file /root/nginx/ssl/cert.pem --key-file /root/nginx/ssl/key.pem --fullchain-file /root/nginx/ssl/fullchain.pem
# DNSPod
/root/acme.sh/acme.sh --issue --dns dns_dp -d hello.com --force --cert-file /root/nginx/ssl/cert.pem --key-file /root/nginx/ssl/key.pem --fullchain-file /root/nginx/ssl/fullchain.pem
然后要实现自动更新域名,只需要把它加到crontab
定时服务即可,这里不赘述。