使用cloudflare CDN的网站获取访客真实IP

之前有一篇文章是介绍宝塔获取cloudflare CDN访客真实IP的文章,但是那篇文章比较粗糙。下面结合cloudflare官方的说明文档,做一些补充说明。

一、CF-Connecting-IP 和 X-Forwarded-For

cloudflare将原始访问者 IP 地址显示在名为 CF-Connecting-IP 和 X-Forwarded-For 的附加 HTTP 标头中。所以你可以选择用:

real_ip_header CF-Connecting-IP; 

或者:

real_ip_header X-Forwarded-For;
real_ip_recursive on;

来获取访客真实IP。

二、ngx_http_realip_module模块

nginx服务器获取realip是依赖ngx_http_realip_module模块的,所以如果你用的是nginx,必须要编译ngx_http_realip_module模块。使用nginx -V命令查看nginx是否已经编译该模块,没有的话需要自己编译。

其它服务器参考cloudflare官方说明文档

三、set_real_ip_from的使用

如果是 set_real_ip_from 0.0.0.0/0; 则表示信任所有前代理传递的真实用户ip,会有安全隐患,我们可以设置为只信任cloudflare的IP:

server
{
listen 443 ssl http2;
listen [::]:80;
server_name 168itw.com;

set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2c0f:f248::/32;
set_real_ip_from 2a06:98c0::/29;

#X-Forwarded-For和CF-Connecting-IP二选一
real_ip_header    X-Forwarded-For;
real_ip_recursive on;
#real_ip_header CF-Connecting-IP; 

cloudflare IP段:https://www.cloudflare.com/ips/

注意:添加在nginx的http{}中,则全局应用在下面的所有server中,即所有网站生效;添加在网站对应的server{}中,则只有该网站中生效。

特别注意:如果同时运行了docker,且有反代docker服务,则需要将docker内网IP段也要加到set_real_ip_from中。

查看docker容器IP:

docker inspect 容器id

添加docker内网IP段:

set_real_ip_from 172.18.0.0/24

四、多级反向代理

如果cloudflare之后还有多级反向代理,可以在cloudflare后的第一级反代只允许cf IP回源,后面的允许上一级反代IP回源。

五、开启CLOUDFLARE的回源认证

cloudflare后台 SSL/TLS – Overview:SSL/TLS encryption mode设置为Full或者Full (strict)

SSL/TLS – Origin Server 开启:Authenticated Origin Pulls

在对应主机的配置文件的server块内加入下列代码:

ssl_client_certificate /etc/nginx/certs/cloudflare.pem;
ssl_verify_client on;

cloudflare.pem文件下载地址:https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/set-up/zone-level/

继续阅读

nginx禁止IP访问目录或文件及location匹配规则

一、关于deny和allow的使用

nginx通过ngx_http_access_module模块来控制IP访问特定路径,可以放在httpserverlocation中。比如:

location / {
    deny  192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    allow 2001:0db8::/32;
    deny  all;
}

nginx按顺序检查规则,直到找到第一个匹配项。注意在使用指令时,如果最后不添加deny all,则可能会允许上面列出ip之外的其他ip均可访问,因为默认是allow all的。

   deny 43.243.12.116;
   deny 43.241.242.243;
   allow all;

所以,上面例子中最后的allow all可以不用添加,因为默认是allow all的。

二、nginx location 配置

  1. 禁止访问某些后缀文件
location ~ \.(ini|conf|txt)$ {
    deny all;
}

2. 禁止访问目录或目录下文件

#禁止访问目录
location ^~ /test/ {
    deny all;
}
#禁止访问目录下文件
location ^~ /test {
    deny all;
}

3. 禁止访问某个目录下的指定文件后缀文件

# 禁止访问某个目录下的 php 后缀文件
location /directory {
    location ~ .*\.(php)?$ {
    deny all;
    }
}
# 禁止访问多个目录下的 php 后缀文件
location ~* ^/(directory1|directory2)/.*\.(php)${
    deny all;
}

location可以嵌套使用,也就是说一个location中可以继续嵌套location。

三、location匹配规则详解

= 表示精确匹配

^~ 表示uri以某个字符串开头

~ 正则匹配(区分大小写)

~* 正则匹配(不区分大小写) !~和!~*分别为区分大小写不匹配及不区分大小写不匹配的正则

/ 任何请求都会匹配

匹配优先级: ​​= > ^~ > /​​

举例:

    location ~ .*\.(json)?$ {
    allow 127.0.0.1/16;
    deny all;
    expires      -1;
    }
  1. location: 表示定义一个匹配规则的位置块。
  2. ~: 表示后面跟着的是一个正则表达式,而不是普通的字符串匹配。
  3. .*: 表示匹配任意字符(除了换行符)零次或多次。这里是匹配任意字符零次或多次,即允许路径中包含任意字符。
  4. \.: 表示匹配点(.)字符。在正则表达式中,点(.)通常表示任意字符,但在这里通过反斜杠进行转义,表示匹配实际的点字符。
  5. (json)?: 表示匹配括号内的内容零次或一次,即json可选。这里的括号用于创建一个捕获组,表示括号内的内容是一个整体,而问号表示前面的字符(这里是 (json))可选。
  6. $: 表示匹配字符串的结尾。

参考文档:

继续阅读

清理docker占用的硬盘空间

docker system 命令

docker system df命令,类似于 Linux 上的df命令,用于查看 Docker 的磁盘使用情况:

docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              147                 36                  7.204GB             3.887GB (53%)
Containers          37                  10                  104.8MB             102.6MB (97%)
Local Volumes       3                   3                   1.421GB             0B (0%)
Build Cache                                                 0B                  0B

docker system prune命令可以用于清理磁盘,删除关闭的容器、无用的数据卷和网络,以及 dangling 镜像(即无 tag 的镜像)。

docker system prune -a命令清理得更加彻底,可以将没有容器使用 Docker 镜像都删掉。

注意,这两个命令会把你暂时关闭的容器,以及暂时没有用到的 Docker 镜像都删掉了…所以使用之前一定要想清楚吶。

手动清理

  1. 清理无用的容器

使用命令docker ps -a列出所有容器,找出不再需要的容器,使用命令docker rm <container_id>删除它们。在删除容器之前,可以使用命令docker stop <container_id>先停止容器。

  1. 清理无用的镜像

使用命令docker images列出所有镜像,找出不再需要的镜像,使用命令docker image rm <image_id>删除它们。在删除镜像之前,可以使用命令docker stop <container_id>先停止容器。

  1. 清理无用的数据卷

使用命令docker volume ls列出所有数据卷,找出不再需要的数据卷,使用命令docker volume rm <volume_name>删除它们。在删除数据卷之前,需要先删除使用该数据卷的容器。

  1. 清理无用的网络

使用命令docker network ls列出所有网络,找出不再需要的网络,使用命令docker network rm <network_name>删除它们。在删除网络之前,需要先删除使用该网络的容器。

5. 清理Docker日志

Docker日志会占用大量空间,可以使用命令docker logs --tail 50 <container_id>来查看最近50行的日志。如果需要清理全部日志,可以使用命令truncate -s 0 /var/lib/docker/containers/*/*/*.log来清空所有日志文件。

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可以很好的解决这个问题。

该模块有三个指令,分别为:secure_link、secure_link_md5、secure_link_secret,使用方法有两种:

  1. secure_link + secure_link_secret(v0.7.18以后);
  2. secure_link + secure_link_md5(v0.8.5以后,其实就是用来替代第一种的)。

后面的部署过程我们都是采用方法2。

secure_link + secure_link_md5基本原理

  1. 把一些参数以及过期时间按你想要的顺序拼成一个字符串,然后对它做md5计算,然后把这个md5和过期时间以参数的方式附加到链接后面。
  2. 在nginx中我们配置同样的参数串顺序,nginx会按我们给出的参数串计算出它的md5值,然后把它计算得到的md5值与链接中传过来的md5值作对比,如果两个值不相同,则会把变量$secure_link设置为空字符串。
  3. 如果md5值相同,nginx还会继续对比过期时间,如果链接已经过期(其实就是当前时间戳大于链接中传过来的时间戳),那么它会把$secure_link的值置为”0″,否则为”1″。
  4. 综上,我们只需要用if检测$secure_link的值,如果为空,则说明这个链接不是合法链接,如果不为空,则继续用if检测它的值是否为”0″,,只要为空或为0,那么我们就可以判断它不是合法请求,就可以用return 403或者rewrite的方式去处理这种不合法请求;

以下记录整个过程。

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代码。

参考文章:https://www.xiebruce.top/1799.html

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