Nginx在实际场景中的妙用
首先,来了解下Nginx是干什么用的?
负载均衡
- 将请求分摊到多个操作单元上进行执行
- 负载均衡策略:
- RR(默认): 顺序轮询访问
- 权重:指定访问比例
- ip_hash: 同一客户端访问同一服务
- fair: 按后端服务器的响应时间来分配请求,响应时间短的优先分配。
- url_hash:固定地址访问固定服务
upstream google{
# 服务器上能访问到google的IP地址,可以通过命令:nslookup www.google.com 解析其IP获取
server 108.177.125.199:443 weight=1 fail_timeout=10s;
server 64.233.189.199:443 weight=1 fail_timeout=10s;
server 172.217.24.68:443 weight=1 fail_timeout=10s;
keepalive 16;
}
Http服务器
- 部署静态资源服务器
- 部署前端HTML代码
server {
listen 80;
server_name edu.seewo.com;
location /res/ {
root /home/www/res/
index index.html
}
}
# 访问地址:https://edu.seewo.com/res/head/1/default.png
反向代理
- 反向代理:以代理服务器来接收请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给请求连接的客户端,客户端并不知道源服务器地址。
- Nginx做的最多的一件事。
server {
listen 80;
server_name backend.fatwo.cn;
location / {
proxy_pass http://localhost:18880;
}
}
正向代理
- 为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
server {
resolver 114.114.114.114 8.8.8.8
resolver_timeout 5s;
listen 88;
location / {
proxy_pass http://$host$request_uri;
}
}
URL重写
server {
rewrite 规则 定向路径 重写类型;
}
- 规则:可以是字符串或者正则来表示想匹配的目标url
- 定向路径:表示匹配到规则后要定向的路径,如果规则里有正则,则可以使用$index来表示正则里的捕获分组
- 重写类型:
- last :相当于Apache里德(L)标记,表示完成rewrite,浏览器地址栏URL地址不变
- break;本条规则匹配完成后,终止匹配,不再匹配后面的规则,浏览器地址栏URL地址不变
- redirect:返回302临时重定向,浏览器地址会显示跳转后的URL地址
- permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
# 案例:
# 将静态资源访问的路由转发到后台服务,支持后台可配置。
server {
listen 80;
server_name edu.seewo.com;
rewrite /res/App.config /api/v1/public/sign/no/appConfig last;
}
# 访问地址:http://edu.seewo.com/res/App.config
通过Nginx如何解决浏览器跨域?
背景
- 浏览器的同源策略:两个页面的协议、端口、主机都相同则同源。
案例:
当前页面:http://frontend.fatwo.cn/ 访问以下资源的结果:
访问URL | 结果 |
---|---|
frontend.fatwo.cn/apis?api=IN… | 允许 |
frontend.fatwo.cn/apis?api=IN… | 跨域:不同协议 |
backend.fatwo.cn/api/v1/info | 跨域:不同域名 |
frontend.fatwo.cn:81/apis?api=IN… | 跨域:不同端口 |
- 同源策略目的:安全考虑。避免不必要的攻击。CSRF攻击就是利用它来实现。
如何解决:
不同资源通过Nginx配置成同源:
- 前端-》访问同域Node层 -》转发到后台接口 同源
- 前端-》访问nginx配置的同域接口 -》转发到后台接口 同源
通过Nginx配置前后端服务同域
upstream frontend-web{
server frontend.fatwo.cn weight=1 fail_timeout=20s;
keepalive 16;
}
upstream backend-server{
server backend.fatwo.cn weight=1 fail_timeout=20s;
keepalive 16;
}
server {
listen 80;
server_name frontend.fatwo.cn;
location / {
proxy_pass http://frontend-web/;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /backend/ {
proxy_pass http://backend-server/;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host "backend.fatwo.cn";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
被访问的资源配置允许跨域: CORS (跨域资源共享)
- 前端-》访问后台支持JSONP方式的接口,输出回调js设置数据到回调函数,不推荐
- 前端-》资源允许跨域(Nginx层、后台服务层),需要严谨处理
通过Nginx解决跨域的配置:
add_header 'Access-Control-Allow-Origin' "http://frontend.fatwo.cn";
add_header 'Access-Control-Allow-Credentials' "true";
if ($request_method = "OPTIONS") {
add_header 'Access-Control-Max-Age' 86400;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
add_header 'Access-Control-Allow-Headers' 'reqid, nid, host, x-real-ip, x-forwarded-ip, event-type, event-id, accept, content-type';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain, charset=utf-8';
return 200;
}
如何通过Nginx访问被墙的google?
- 正常情况下,无法访问:www.google.com/
- 通过Nginx反向代理处理,可访问:search.fatwo.cn/
需要做一些前期准备
准备内容 | 原因 |
---|---|
域名:search.fatwo.cn(可不备案),免费域名申请可上 www.freenom.com | 用于代理转发到:www.google.com |
域名的SSL证书(腾讯云上面申请的免费SSL证书,1年期) | 谷歌需要用https协议来访问,可降低被墙风险。 |
一个香港服务器:47.244.200.85 | 可正常访问谷歌的中转服务器 |
Nginx配置好反向代理 | 将访问到search.fatwo.cn域名的请求反向代理到https://www.google… |
相关Nginx配置如下:
# 通过nslookup获取到的谷歌服务列表
upstream google{
# 服务器上能访问到google的IP地址,可以通过命令:nslookup www.google.com 解析其IP获取
server 108.177.125.199:443 weight=1 fail_timeout=10s;
server 64.233.189.199:443 weight=1 fail_timeout=10s;
server 172.217.24.68:443 weight=1 fail_timeout=10s;
keepalive 16;
}
server{
listen 80;
server_name search.fatwo.cn;
listen 443 ssl;
ssl on;
ssl_certificate /etc/nginx/https/search.fatwo.cn/1_search.fatwo.cn_bundle.crt;
ssl_certificate_key /etc/nginx/https/search.fatwo.cn/2_search.fatwo.cn.key;
access_log /home/logs/google.fatwo.cn.access.log main;
set $toDomain 'www.google.com';
set $sourceDomain 'search.fatwo.cn';
location / {
proxy_redirect off;
proxy_cookie_domain $toDomain $sourceDomain;
proxy_pass https://google;
proxy_connect_timeout 60s;
proxy_read_timeout 5400s;
proxy_send_timeout 5400s;
proxy_set_header Host $toDomain;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header Referer https://$toDomain;
proxy_set_header Accept-Encoding "";
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 https;
proxy_set_header Accept-Language "zh-CN";
}
# 防止网络爬虫,另一个方法是网站根目录下创建Robots.txt
#forbid spider
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot")
{
return 403;
}
}