Cloudflare Cache Rules搭配Page Rules实现灵活缓存

之前有写过Cloudflare Page Rules缓存全站的用法,但是遇到像部分页面不能缓存(类似于动态获取参数等)的时候,Page Rules设置就不够灵活了,而且cloudflare免费账户的3条Page Rules规则,明显不够用,我们就需要配合Cache Rules来使用。

Cache Rules比Page Rules的设置更加灵活方便,而且免费账户支持10条规则。

使用Cache Rules之前,需要先搞清楚它与Page Rules之间的区别:

  1. Cache Rules的优先级高于Page Rules。也就是说,如果Cache Rules中的规则与Page Rules冲突,Cache Rules规则会覆盖Page Rules规则。这就非常适合上面说的情况,用Cache Rules来排除某些不需要缓存的页面。
  2. Cache Rules规则从上往下,权重是递增的。也就是说,如果规则有冲突,下面的规则会覆盖上面的规则。

详细说明参考Cloudflare官方:https://developers.cloudflare.com/cache/how-to/cache-rules/

下面以wordpress为例,来设置Cloudflare Cache Rules搭配Page Rules实现灵活缓存规则。相比之前的设置,做了进一步的优化。

Page Rules规则

  1. URL: www.168itw.com/wp-admin*
    Cache Level: Bypass
    Disable Performance
  2. URL: www.168itw.com/*php*
    Cache Level: Bypass
    Disable Performance
  3. URL: www.168itw.com/*
    Cache Level: Cache Everything
    Edge Cache TTL: a day

规则1不缓存wordpress后台。

规则2不缓存特殊动态页面,比如动态支付页面,动态API页面,这就需要根据自己的页面结构来确定URL特性;当然这里也包括了wordpress后台登录页面wp-login.php。

规则3缓存全站,包括首页,缓存时间为1天。

Cache Rules规则

以影视站点为例,我需要用nginx对电视剧频道的视频鉴权防盗链(Nginx secure_link模块给网站添加防盗链),所以该频道页面需要动态生成鉴权token,因此不能按照Page Rules规则来缓存1天。

  1. Rule name: tv channels cache rule
    When incoming requests match…
    URI Path – Contains – /tv And
    Hostname – equals – www.168itw.com
    Cache status
    Bypass cache
    Browser TTL
    Respect origin
  2. Rule name: css & js & woff & img cache rule
    When incoming requests match…
(http.request.uri contains ".css") or (http.request.uri contains ".js") or (http.request.uri contains ".woff") or (http.request.uri contains ".jpg") or (http.request.uri contains ".png") or (http.request.uri contains ".svg") or (http.request.uri contains ".gif") or (http.request.uri contains ".bmp") or (http.request.uri contains ".ico")

Cache status
Eligible for cache
Edge TTL
7 days
Browser TTL
Override origin – 1 day

这里需要说明下:

规则1中Browser TTL设置为Respect origin,即浏览器缓存,按照默认的浏览器缓存设置来,默认设置在cloudflare的Caching – Configuration中,默认是30minutes,你也可以根据需要来修改。因为我的nginx鉴权设定为3小时,所以用户浏览器缓存30分钟是完全没问题的。

规则2是缓存css、js、woff字体、jpg等图片,因为规则1排除了tv目录下所有页面的缓存,但是这些页面上的静态资源是可以缓存的;当然,该条规则也会覆盖掉Page Rules中对于静态规则的缓存设置,因为它的优先级比较高。

nginx使用replace-filter-nginx-module模块正则替换

nginx反代,要实现内容替换,sub_filter功能有限,而且不支持正则匹配;本来开始是使用ngx_http_substitutions_filter,发现怎么都不起作用,也不知道是哪里问题。后来找到一个更加强大的替换模块:replace-filter-nginx-module

GitHub地址:https://github.com/openresty/replace-filter-nginx-module

安装此模块需要先安装sregex运行库。

cd /www/server/nginx/src
git clone https://github.com/agentzh/sregex
cd sregex
make
make install

安装 replace-filter-nginx-module

cd /www/server/nginx/src
git clone https://github.com/agentzh/replace-filter-nginx-module

nginx -V查看,添加replace-filter-nginx-module编译:

./configure --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --add-module=/www/server/nginx/src/ngx_http_substitutions_filter_module-master --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module --with-http_secure_link_module --add-module=/www/server/nginx/src/replace-filter-nginx-module

安装之后,替换nginx

make
cp /www/server/nginx/sbin/nginx /www/server/nginx/sbin/nginx.bak
nginx -s stop
cp /www/server/nginx/src/objs/nginx /www/server/nginx/sbin/nginx
service nginx restart

重启nginx的时候发现报错了:

error while loading shared libraries: libsregex.so.0: cannot open shared object file: No such file or directory

查看时哪里的问题:

ldd $(which /www/server/nginx/sbin/nginx)

发现 libsregex.so.0 => not found,nginx只从/lib/x86_64-linux-gn路径下寻找,那么我们将类库直接复制过去就行:

cp /www/server/nginx/src/sregex/libsregex.so.0 /lib/x86_64-linux-gnu

再次重启nginx,就没问题了:

service nginx restart

查看nginx -V,确认模块安装成功。

关于replace-filter-nginx-module正则替换规则,可以参看GitHub说明。

Nginx secure_link模块给网站添加防盗链

网站上的一些静态资源文件,比如图片、pdf、压缩文件、m3u8等视频文件,经常会被盗链,之前我都是用referrer来防盗链,但是referrer太容易伪造了。后来nginx的secure_link可以很好的解决这个问题。

它的主要原理是,通过验证 URL 中哈希值的方式防盗链。

基本过程是这个样子的:

  • 由服务器(可以是 Nginx,也可以是其他 Web 服务器)生成加密的安全链接 URL,返回给客户端
  • 客户端使用安全 URL 访问 Nginx,由 Nginx 的 secure_link 变量验证是否通过

原理如下:

  • 哈希算法是不可逆的
  • 客户端只能拿到执行过哈希算法的 URL
  • 仅生成 URL 的服务器,验证 URL 是否安全的 Nginx,这两者才保存原始的字符串
  • 原始字符串通常由以下部分有序组成:
    • 资源位置。如 HTTP 中指定资源的 URI,防止攻击者拿到一个安全 URI 后可以访问任意资源
    • 用户信息。如用户的 IP 地址,限制其他用户盗用 URL
    • 时间戳。使安全 URL 及时过期
    • 密钥。仅服务器端拥有,增加攻击者猜测出原始字符串的难度。

以下记录整个过程。

1、编译secure_link模块

我用的是宝塔,默认是没有编译secure_link,通过查看nginx -V确认下:

/www/server/nginx/sbin/nginx -V
cd /www/server/nginx/src/

在最后面添加–with-http_secure_link_module,编译:

./configure  --user=www --group=www --prefix=/www/server/nginx --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-openssl=/www/server/nginx/src/openssl --with-pcre=pcre-8.43 --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_stub_status_module --with-http_ssl_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-cc-opt=-Wno-error --with-ld-opt=-ljemalloc --with-http_dav_module --add-module=/www/server/nginx/src/nginx-dav-ext-module --with-http_secure_link_module
make

备份nginx:

cp /www/server/nginx/sbin/nginx /www/server/nginx/sbin/nginx.bak

停止nginx:

nginx -s stop

继续:

cp /www/server/nginx/src/objs/nginx /www/server/nginx/sbin/nginx

然后启动nginx

systemctl restart nginx

查看nginx -V是否成功编译secure_link模块:

/www/server/nginx/sbin/nginx -V

2、Nginx配置

location /yourpath/ {
    secure_link $arg_md5,$arg_expires; #这里配置了2个参数一个是arg_md5,一个是arg_expires
    secure_link_md5 "123456$uri$arg_expires"; #123456为自定义的加密串(这里的md5加密顺序要和程序生成的加密顺序保持一致)   

    if ($secure_link = "") {
        return 403; #资源不存在或哈希比对失败
    }

    if ($secure_link = "0") {
        return 410; #时间戳过期 
    }
}

3、配置网站PHP

<?php
$secret = '123456';

####下载文件,切记路径带上/
$path = "/file/168itw.zip";

####下载到期时间,time是当前时间,$validtime表示有效期,也就是说从现在到300秒之内文件不过期
$validtime = 300;
$expire = time() + $validtime;

####用文件路径、密钥、过期时间生成加密串(注意这里的md5加密顺序要和nginx配置文件中的顺序保持一致)
$md5 = base64_encode(md5($secret . $path . $expire, true));
$md5 = strtr($md5, '+/', '-_');
$md5 = str_replace('=', '', $md5);

####加密后的下载地址
$uri = $path . '?md5=' . $md5 . '&expires=' . $expire;

####安全下载链接可以直接echo输出
$uri = "https://www.168itw.com" . $uri;
?>

输出上述文件链接:

<?php echo $uri; ?>

如果使用的是wordpress,需要在文章post中添加防盗链文件,可以安装Insert PHP Code Snippet插件,这样就可以在任意文章中任何位置插入PHP代码。

RealVNC: VNC Server has no authentication schemes configured错误

RealVNC连接远程server端的时候,提示:VNC Server has no authentication schemes configured. 错误。

解决方法:

  1. 在server端打开Powershell
  2. 输入以下命令:
New-ItemProperty -Path "HKLM:\Software\RealVNC\vncserver" -Name "Authentication" -Value "VncAuth"
& "C:\Program Files\RealVNC\VNC Server\vncpasswd.exe" -service

按提示输入密码。

重新连接realvnc,输入刚才的密码即可成功连接。

Linux设置IPv4优先

IPv6 VPS套了warp后变成了IPv4和IPv6双栈,如何设置IPv4优先呢?

以debain为例,直接修改 /etc/gai.conf 文件:

vi /etc/gai.conf

#precedence ::ffff:0:0/96 100
把前面的”#”去掉即可。

或者:

echo "precedence ::ffff:0:0/96 100" >>/etc/gai.conf

Debian部署go项目

第一次部署go项目,记录一下过程。

首先update一下:

apt update
apt upgrade

安装nodejs:

apt install nodejs

安装npm:

apt install npm

安装pm2:

npm install pm2 -g

将编译好的go项目文件上传到对应目录之后:

chmod +x golang

运行go项目:

pm2 start golang

查看:

pm2 ls

Linux设置swap交换分区

以debian为例。

创建交换空间文件/swapfile,大小是1G:

fallocate -l 1G /swapfile

默认交换空间文件的权限只有root用户才能写入和读取交换文件的数据。因此我们需要修改交换空间文件的权限为600,并使用mkswap格式化文件。

chmod 600 /swapfile
mkswap /swapfile

启用交换空间:

swapon /swapfile

要在Linux系统启动时自动挂载分区,需要在/etc/fstab文件中定义挂载配置选项:

echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab

运行命令swapon或free命令验证交换空间是否处于活动状态:

swapon --show
free -h

Swappiness

Swappiness是一个Linux内核属性,用于定义系统使用交换空间的频率。Swappiness可以是0到100之间的值。

swappiness=0的时候表示最大限度使用物理内存,然后才是交换空间,swappiness=100的时候表示积极的使用交换空间。

Linux的初始默认设置为60,你可以运行命令cat /proc/sys/vm/swappiness命令查看当前swappiness值的大小。

如果你需要对swappiness的值作出更改,请运行sudo sysctl -w vm.swappiness=10命令。

sysctl命令用于在运行时配置Linux内核的参数,更改仅在当前会话中可用,即重启会恢复为默认值。

为让swappiness的值持久化,则需要将值写入到/etc/sysctl.conf文件中。sysctl.conf是Linux内核的配置文件。在Linux内核启动是将会次配置文件的参数。

运行以下命令持久化Linux内核参数swappiness的值:

echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/sysctl.conf

FFmpeg循环推流脚本

转载过来备用,原文链接见文章结尾。

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#=================================================================#
#   System Required: CentOS7 X86_64                               #
#   Description: FFmpeg Stream Media Server                       #
#   Author: LALA                                    #
#   Website: https://www.lala.im                                  #
#=================================================================#

# 颜色选择
red='\033[0;31m'
green='\033[0;32m'
yellow='\033[0;33m'
font="\033[0m"

ffmpeg_install(){
# 安装FFMPEG
read -p "你的机器内是否已经安装过FFmpeg4.x?安装FFmpeg才能正常推流,是否现在安装FFmpeg?(yes/no):" Choose
if [ $Choose = "yes" ];then
	yum -y install wget
	wget --no-check-certificate https://www.johnvansickle.com/ffmpeg/old-releases/ffmpeg-4.0.3-64bit-static.tar.xz
	tar -xJf ffmpeg-4.0.3-64bit-static.tar.xz
	cd ffmpeg-4.0.3-64bit-static
	mv ffmpeg /usr/bin && mv ffprobe /usr/bin && mv qt-faststart /usr/bin && mv ffmpeg-10bit /usr/bin
fi
if [ $Choose = "no" ]
then
    echo -e "${yellow} 你选择不安装FFmpeg,请确定你的机器内已经自行安装过FFmpeg,否则程序无法正常工作! ${font}"
    sleep 2
fi
	}

stream_start(){
# 定义推流地址和推流码
read -p "输入你的推流地址和推流码(rtmp协议):" rtmp

# 判断用户输入的地址是否合法
if [[ $rtmp =~ "rtmp://" ]];then
	echo -e "${green} 推流地址输入正确,程序将进行下一步操作. ${font}"
  	sleep 2
	else  
  	echo -e "${red} 你输入的地址不合法,请重新运行程序并输入! ${font}"
  	exit 1
fi 

# 定义视频存放目录
read -p "输入你的视频存放目录 (格式仅支持mp4,并且要绝对路径,例如/opt/video):" folder

# 判断是否需要添加水印
read -p "是否需要为视频添加水印?水印位置默认在右上方,需要较好CPU支持(yes/no):" watermark
if [ $watermark = "yes" ];then
	read -p "输入你的水印图片存放绝对路径,例如/opt/image/watermark.jpg (格式支持jpg/png/bmp):" image
	echo -e "${yellow} 添加水印完成,程序将开始推流. ${font}"
	# 循环
	while true
	do
		cd $folder
		for video in $(ls *.mp4)
		do
		ffmpeg -re -i "$video" -i "$image" -filter_complex overlay=W-w-5:5 -c:v libx264 -c:a aac -b:a 192k -strict -2 -f flv ${rtmp}
		done
	done
fi
if [ $watermark = "no" ]
then
    echo -e "${yellow} 你选择不添加水印,程序将开始推流. ${font}"
    # 循环
	while true
	do
		cd $folder
		for video in $(ls *.mp4)
		do
		ffmpeg -re -i "$video" -c:v copy -c:a aac -b:a 192k -strict -2 -f flv ${rtmp}
		done
	done
fi
	}

# 停止推流
stream_stop(){
	screen -S stream -X quit
	killall ffmpeg
	}

# 开始菜单设置
echo -e "${yellow} CentOS7 X86_64 FFmpeg无人值守循环推流 For LALA.IM ${font}"
echo -e "${red} 请确定此脚本目前是在screen窗口内运行的! ${font}"
echo -e "${green} 1.安装FFmpeg (机器要安装FFmpeg才能正常推流) ${font}"
echo -e "${green} 2.开始无人值守循环推流 ${font}"
echo -e "${green} 3.停止推流 ${font}"
start_menu(){
    read -p "请输入数字(1-3),选择你要进行的操作:" num
    case "$num" in
        1)
        ffmpeg_install
        ;;
        2)
        stream_start
        ;;
        3)
        stream_stop
        ;;
        *)
        echo -e "${red} 请输入正确的数字 (1-3) ${font}"
        ;;
    esac
	}

# 运行开始菜单
start_menu
继续阅读

Prometheus+Grafana运维级监控部署

在之前的网站uptime监控中提到过Prometheus+Grafana监控搭配,抽空自己部署了一遍,功能强大,达到了运维级。

Prometheus是主控程序,是监控的Server端。

Node exporter是client端,部署在被监控vps上,负责向Prometheus传输数据。

Grafana是开源的看板/面板程序,提供可视化图形界面。

三者相结合,提供了一套完整的运维级监控系统。如果需要监控警报,还需要加入Alertmanager。

Prometheus、Node exporter、Altermanager开源地址:

https://github.com/prometheus

Grafana开源地址:https://github.com/grafana/grafana

下面记录下部署过程。

1、docker部署Prometheus

选择用docker部署,简单方便。注意映射9090端口,及prometheus.yml配置文件目录。我这里以/opt/config目录为例:

-v /opt/config:/etc/prometheus

将宿主机/opt/config目录,挂载到docker的/etc/prometheus目录。

如果是二进制安装,步骤为:

tar zxf prometheus-2.25.0.linux-amd64.tar.gz -C /opt
mv /opt/prometheus-2.25.0.linux-amd64 /opt/prometheus
vim /usr/lib/systemd/system/prometheus.service
[Unit]
Description=prometheus service
 
[Service]
User=root
ExecStart=/opt/prometheus/prometheus --config.file=/opt/prometheus/prometheus.yml --storage.tsdb.path=/opt/prometheus/data
 
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
 
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable prometheus
systemctl start prometheus
systemctl status prometheus

每次更改了Prometheus配置文件,都需要重启:

systemctl restart prometheus

2、配置prometheus.yml文件

以下为最简单的默认配置文件

global:
  scrape_interval:     15s # By default, scrape targets every 15 seconds.

  # Attach these labels to any time series or alerts when communicating with
  # external systems (federation, remote storage, Alertmanager).
  external_labels:
    monitor: 'codelab-monitor'

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # Override the global default and scrape targets from this job every 5 seconds.
    scrape_interval: 5s

    static_configs:
      - targets: ['localhost:9100']
        labels:
          instance: prometheus

添加配置文件之后,docker程序才能正常启动。

此时访问http://ip:9090端口,访问Prometheus控制界面。目前界面很简陋,所以需要继续部署grafana。

3、部署Grafana面板程序

以debian为例:

sudo apt-get install -y apt-transport-https
sudo apt-get install -y software-properties-common wget
sudo wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key

添加源:

echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list

安装grafana:

sudo apt-get update
sudo apt-get install grafana

启动Grafana:

sudo systemctl daemon-reload
sudo systemctl start grafana-server
sudo systemctl status grafana-server

配置随机启动:

sudo systemctl enable grafana-server.service

浏览器访问IP:3000端口,即可打开grafana页面,默认用户名密码都是admin,初次登录会要求修改默认的登录密码。

4、为Grafana添加Prometheus数据源

点击主界面的“Add your first data source”并选择Prometheus,import,保存即可。

当然你还可以添加更多目标,看到更多详细的数据,Grafana官方也提供了很多dashboard的模板:

https://grafana.com/grafana/dashboards/

推荐排名第一的Node Exporter Full。安装模板也很简单,直接复制模板ID(Copy ID to clipboard)

Grafana后台 – Dashboards – Browse – New – Import – 粘贴ID – Load – 并选择数据源为Prometheus。搞定

5、部署Node exporter

在需要被监控的vps上部署node exporter,当然也可以在Prometheus所在vps上部署,监控本机。

选择下载对应版本并解压:

wget https://github.com/prometheus/node_exporter/releases/download/v1.5.0/node_exporter-1.5.0.linux-amd64.tar.gz
tar xvfz node_exporter-1.5.0.linux-amd64.tar.gz
mv /root/node_exporter-1.5.0.linux-amd64 /opt/node_exporter

配置开机启动:

vi /usr/lib/systemd/system/node_exporter.service
[Unit]
Description=node_exporter service
 
[Service]
User=root
ExecStart=/opt/node_exporter/node_exporter
 
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
 
[Install]
WantedBy=multi-user.target

如果报错,也可以 vi /etc/systemd/system/node_exporter.service

关于Linux service配置文件的说明,请参考:https://wizardforcel.gitbooks.io/vbird-linux-basic-4e/content/150.html

systemctl daemon-reload
systemctl enable node_exporter

启动服务:

systemctl start node_exporter
systemctl status node_exporter

node exporter默认监控端口是9100,访问ip:9100可以查看node exporter。

注意:在vps面板防火墙中放行9100端口,同时如果vps安装了宝塔等程序,也需要在”安全“中放行9100端口。

iptables也要放行9100:

iptables -I INPUT -s 0.0.0.0/0 -p tcp --dport 9100 -j ACCEPT

6、Node exporter与Prometheus建立连接,传送数据。

编辑Prometheus的prometheus.yml文件,添加以下代码,注意对齐:

  - job_name: 'Linux'
    static_configs:
      - targets: ['xx.xx.xx.xx:9100']
        labels:
          instance: 168itw.com

重启docker Prometheus。

继续阅读