利用cloudflare访问被墙的VPS(web和vpn)

最近vps频繁被墙,中途尝试过host winds,尽管hostwinds可以换ip,可是最近一次被墙后换了n次IP也没通,不想折腾了,牺牲点速度用cloudflare吧。vps主要是放个blog,再搭建个私有vpn偶尔上谷歌查查文献。

1、利用cloudflare访问被墙的web。这个很简单,网上教程一大堆,主要是把自己的域名加到cloudflare里面,把nameserver也改成cloudflare的,添加A记录到vps的ip,打开代理(灰云变成黄云),等dns服务器刷新(约3-6分钟)后,再次访问就通了,可能速度会变慢,还有个好处是隐藏真实ip地址。

2、vpn。目前v2ray比较流行,以centos安装v2ray为例,比较好用的脚本是233blog的。在安装v2ray之前得在cloudflare里面新建一个vpn专用域名解析,比如vpn.xxx.com指向100.200.100.200,暂时关闭代理状态,也就是灰云。再在root命令行模式下输入:bash <(curl -s -L https://git.io/v2ray.sh),会出现下图(借个图,不要照图抄,图上的设置用不了域名,用ip的话,ip又被墙了):

传输协议选择4,websocket+tls。

端口选择很关键,因为cloudflare有端口限制,自己去cloudflare网上查:https://developers.cloudflare.com/fundamentals/get-started/reference/network-ports/。

输入域名(刚才在cloudflare里面建好的),如果解析已经生效了(不要开启cloudflare代理),安装会继续向前,否则就会提示错误并停止安装。

如果协议选择4,后面还会让选择是否自动配置tls,选择是继续,安装caddy(因为已经有nginx了,所以安装好就把caddy停了)。

广告拦截和ss都默认选否就行。

接下来放几张相对正确的有参考意义的图(借个图):

安装好后会显示配置信息,当然,如果用了233blog的脚本,后期随时可以用“v2ray”命令调出选项菜单,根据需要进行各种操作和查看。同时,会发现配置信息里的端口是443(没错你刚才设置的不是443,443端口是https或者tls协议要用到的端口,我们在客户端输入的端口都是443,tls证书怎么搞就不写了,自己上网查吧)。

还记不记得刚才自动安装的caddy,如果你有nginx和宝塔,可以在命令行输入“service caddy stop”来停止这个服务,这是一个web服务,在233blog的脚本中是用来建立反向代理的,即当cloudflare解析到vps时用的时443端口,需要从服务器内部“转发”至刚才你设置的端口上(比如上图的8844,因为是服务器内部“转发”所以地址就是127.0.0.1:8844),这个功能nginx完全可以胜任。

只要在集成nginx的宝塔面板新建网站vpn.xxx.com(前面设定的vpn域名),静态页面就行,然后在网站设置里找到反向代理一栏,新建反向代理,目标地址里设置“http://127.0.0.1:8844”(不需要加引号),随便输入最上方的别名确定保存。

保险起见,重启v2ray和nginx,不知道怎么重启的直接在命令行打入“reboot”。

然后再cloudflare里面把黄云点亮,开启代理。

最后,客户端设置,就照着刚安装好v2ray时显示的信息设置就行,保存,点击连接就ok了。

因为我很懒,对大部分人来说这个看着很乱,总体思路就是我们通过vpn客户端访问域名(因为ip被封了),域名通过cloudflare解析到cloudflare的cdn节点(这个节点可以连通你的网络和vps的网络),然后cdn节点解析到VPS,这个访问通过tls即443端口连接,然而v2ray服务端口是8844(举例),这就需要在vps本地建立一个反向代理,把外部的请求“转发”到8844端口,完整地址就是127.0.0.1:8844(本服务器地址可以写localhost或127.0.0.1),实际上这是一个双向通讯的过程,所以“转发”两个字加了引号。

nginx中性能需要调整,参考:https://blog.csdn.net/weixin_44972135/article/details/92806391

当v2ray连接不稳定时可能是被防火墙封了,需要检查防火墙日志,可能会被误判cc攻击,将相关内容加入白名单就行。

禁用wpjam首页获取文章第一张图

之前一直用wpjam basic来在首页显示文章第一张图片,最近发现wpjam好像会影响页面加载速度,禁用之后速度明显变快,于是尝试自己加代码。

1、在主题编辑器中编辑function.php,在最后加入如下代码:

function catch_that_image() {
global $post, $posts;
$first_img = '';
ob_start();
ob_end_clean();
$output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);

$first_img = '';
if(empty($matches[1])) $first_img = "";
else $first_img = $matches [1][0];
return $first_img;
}

2、在主题编辑器中编辑content-search.php,在第22行插入:

<?php

if(catch_that_image()){?>

<div align=”center”>
<img src="<?php echo catch_that_image(); ?>" width="600" >
</div>
<?php } ?>

3、在该主题目录下修改index.php第39行为“get_template_part( ‘content-search’, get_post_format() );”。这一点操作在以前的文章也提到过:wp主题twentyfifteen首页布局的修改

禁用优化插件获得效率提升

今天心血来潮,把所有插件都禁用了,然后一个一个打开,测试页面打开速度,结果发现一些所谓的优化插件(WP-Optimize、W3 Total cache)都会影响网页打开速度,对个人博客来说,这简直是负优化啊,可能当访问量很大的时候需要用到这类插件,至少目前低负载情况下这两个插件对网页打开速度的影响是明显的。

本站优化7:waf防火墙改进动态封禁ip

此文转载自:斐斐のBlog

原文地址:宝塔面板Nginx的Lua-Waf防火墙终极改进 动态封禁IP

实在没有需要修改的地方,就连理由都一样,原文如下:

宝塔面板自带的Nginx防火墙有些鸡肋,对于大量的恶意攻击只能临时拦截,而不能封禁IP,下面的修改可以帮你做到:

CC攻击屡教不改,立即ban!

漏洞扫描屡教不改:立即ban!

同一个IP段轮流攻击,整个IP段都给你ban了!

使用了CDN?没关系,获取了真实IP再ban!

一小时后,unban……

宝塔面板的nginx修改/www/server/nginx/waf/目录下的三个文件即可,如果没有宝塔面板,nginx必须安装Lua,然后对下面的代码稍加修改,并且自己加上正则黑名单(或者下载个宝塔面板把规则文件拷出来)也可以正常使用。

代码:config.lua

RulePath = "/www/server/panel/vhost/wafconf/"    --规则文件夹
attacklog="on"
logdir = "/www/wwwlogs/waf/"    --日志文件夹
UrlDeny="on"
Redirect="on"
CookieMatch="on"
postMatch="on"
whiteModule="on" 
black_fileExt={"php"}
ipWhitelist={}
ipBlocklist={}
CCDeny="on"
CCrate="500/100"    --这个是CC攻击的几秒钟允许请求几次

代码:init.lua

require 'config'
local match = string.match
local ngxmatch=ngx.re.find
local unescape=ngx.unescape_uri
local get_headers = ngx.req.get_headers
local optionIsOn = function (options) return options == "on" and true or false end
logpath = logdir 
rulepath = RulePath
UrlDeny = optionIsOn(UrlDeny)
PostCheck = optionIsOn(postMatch)
CookieCheck = optionIsOn(cookieMatch)
WhiteCheck = optionIsOn(whiteModule)
PathInfoFix = optionIsOn(PathInfoFix)
attacklog = optionIsOn(attacklog)
CCDeny = optionIsOn(CCDeny)
Redirect=optionIsOn(Redirect)
function subString(str, k)    --截取字符串
    ts = string.reverse(str)
    _, i = string.find(ts, k)
    m = string.len(ts) - i + 1
    return string.sub(str, 1, m)
end
function getClientIp()
        IP  = ngx.var.remote_addr 
    if ngx.var.HTTP_X_FORWARDED_FOR then
      IP = ngx.var.HTTP_X_FORWARDED_FOR
    end
        if IP == nil then
                IP  = "unknown"
        end
    IP = subString(IP, "[.]") .. "*"
        return IP
end
function getRealIp()
        IP  = ngx.var.remote_addr 
    if ngx.var.HTTP_X_FORWARDED_FOR then    --如果用了CDN,判断真实IP
      IP = ngx.var.HTTP_X_FORWARDED_FOR
    end
        if IP == nil then
                IP  = "unknown"
        end
    return IP
end
function write(logfile,msg)
    local fd = io.open(logfile,"ab")
    if fd == nil then return end
    fd:write(msg)
    fd:flush()
    fd:close()
end
function log(method,url,data,ruletag)
    if attacklog then
        local realIp = getRealIp()
        local ua = ngx.var.http_user_agent
        local servername=ngx.var.server_name
        local time=ngx.localtime()
        if ua  then
            line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\"  \""..ua.."\" \""..ruletag.."\"\n"
        else
            line = realIp.." ["..time.."] \""..method.." "..servername..url.."\" \""..data.."\" - \""..ruletag.."\"\n"
        end
        local filename = logpath..'/'..servername.."_"..ngx.today().."_sec.log"
        write(filename,line)
    end
end
------------------------------------规则读取函数-------------------------------------------------------------------
function read_rule(var)
    file = io.open(rulepath..'/'..var,"r")
    if file==nil then
        return
    end
    t = {}
    for line in file:lines() do
        table.insert(t,line)
    end
    file:close()
    return(t)
end
-----------------------------------频繁扫描封禁ip-------------------------------------------------------------------
function ban_ip(point)
    local token = getClientIp() .. "_WAF"
    local limit = ngx.shared.limit
    local req,_=limit:get(token)
    if req then
    limit:set(token,req+point,3600)  --发现一次,增加积分,1小时内有效
    else
    limit:set(token,point,3600)
    end
end

function get_ban_times()
  local token = getClientIp() .. "_WAF"
  local limit = ngx.shared.limit
        local req,_=limit:get(token)
  if req then
    return req
  else return 0
  end
end

function is_ban()
  local ban_times = get_ban_times()
  if ban_times >= 100 then        --超过100积分,ban
    ngx.header.content_type = "text/html;charset=UTF-8"
    ngx.status = ngx.HTTP_FORBIDDEN
    ngx.exit(ngx.status)
    return true
  else
    return false
  end
  return false
end

urlrules=read_rule('url')
argsrules=read_rule('args')
uarules=read_rule('user-agent')
wturlrules=read_rule('whiteurl')
postrules=read_rule('post')
ckrules=read_rule('cookie')
html=read_rule('returnhtml')

function say_html()
  ban_ip(15)      --恶意攻击,罚15分
    if Redirect then
        ngx.header.content_type = "text/html;charset=UTF-8"
    ngx.status = ngx.HTTP_FORBIDDEN
        ngx.say(html)
        ngx.exit(ngx.status)
    end
end

function whiteurl()
    if WhiteCheck then
        if wturlrules ~=nil then
            for _,rule in pairs(wturlrules) do
                if ngxmatch(ngx.var.uri,rule,"isjo") then
                    return true 
                 end
            end
        end
    end
    return false
end
function fileExtCheck(ext)
    local items = Set(black_fileExt)
    ext=string.lower(ext)
    if ext then
        for rule in pairs(items) do
            if ngx.re.match(ext,rule,"isjo") then
          log('POST',ngx.var.request_uri,"-","file attack with ext "..ext)
            say_html()
            end
        end
    end
    return false
end
function Set (list)
  local set = {}
  for _, l in ipairs(list) do set[l] = true end
  return set
end
function args()
    for _,rule in pairs(argsrules) do
        local args = ngx.req.get_uri_args()
        for key, val in pairs(args) do
            if type(val)=='table' then
                 local t={}
                 for k,v in pairs(val) do
                    if v == true then
                        v=""
                    end
                    table.insert(t,v)
                end
                data=table.concat(t, " ")
            else
                data=val
            end
            if data and type(data) ~= "boolean" and rule ~="" and ngxmatch(unescape(data),rule,"isjo") then
                log('GET',ngx.var.request_uri,"-",rule)
                say_html()
                return true
            end
        end
    end
    return false
end


function url()
    if UrlDeny then
        for _,rule in pairs(urlrules) do
            if rule ~="" and ngxmatch(ngx.var.request_uri,rule,"isjo") then
                log('GET',ngx.var.request_uri,"-",rule)
                say_html()
                return true
            end
        end
    end
    return false
end

function ua()
    local ua = ngx.var.http_user_agent
    if ua ~= nil then
        for _,rule in pairs(uarules) do
            if rule ~="" and ngxmatch(ua,rule,"isjo") then
                log('UA',ngx.var.request_uri,"-",rule)
                say_html()
              return true
            end
        end
    end
    return false
end
function body(data)
    for _,rule in pairs(postrules) do
        if rule ~="" and data~="" and ngxmatch(unescape(data),rule,"isjo") then
            log('POST',ngx.var.request_uri,data,rule)
            say_html()
            return true
        end
    end
    return false
end
function cookie()
    local ck = ngx.var.http_cookie
    if CookieCheck and ck then
        for _,rule in pairs(ckrules) do
            if rule ~="" and ngxmatch(ck,rule,"isjo") then
                log('Cookie',ngx.var.request_uri,"-",rule)
                say_html()
            return true
            end
        end
    end
    return false
end

function denycc()
    if CCDeny then
        CCcount=tonumber(string.match(CCrate,'(.*)/'))
        CCseconds=tonumber(string.match(CCrate,'/(.*)'))
        local token = getRealIp()
        local limit = ngx.shared.limit
        local req,_=limit:get(token)
        if req then
            if req > CCcount then
         limit:incr(token,1)
         ban_ip(req - CCcount)  --CC攻击,罚分
         ngx.header.content_type = "text/html"
         ngx.status = ngx.HTTP_FORBIDDEN
                 ngx.say("老哥你手速也忒快了吧,要不休息"..CCcount.."秒?")
                 ngx.exit(ngx.status)
                 return true
            else
                 limit:incr(token,1)
            end
        else
            limit:set(token,1,CCseconds)
        end
    end
    return false
end

function get_boundary()
    local header = get_headers()["content-type"]
    if not header then
        return nil
    end

    if type(header) == "table" then
        header = header[1]
    end

    local m = match(header, ";%s*boundary=\"([^\"]+)\"")
    if m then
        return m
    end

    return match(header, ";%s*boundary=([^\",;]+)")
end

function whiteip()
    if next(ipWhitelist) ~= nil then
        for _,ip in pairs(ipWhitelist) do
            if getClientIp()==ip then
                return true
            end
        end
    end
        return false
end

function blockip()
     if next(ipBlocklist) ~= nil then
         for _,ip in pairs(ipBlocklist) do
             if getClientIp()==ip then
                 ngx.exit(444)
                 return true
             end
         end
     end
         return false
end

代码:waf.lua

local content_length=tonumber(ngx.req.get_headers()['content-length'])
local method=ngx.req.get_method()
local ngxmatch=ngx.re.match
if whiteip() then
elseif blockip() then
elseif whiteurl() then
elseif is_ban() then
elseif denycc() then
elseif ngx.var.http_Acunetix_Aspect then
    ngx.exit(444)
elseif ngx.var.http_X_Scan_Memo then
    ngx.exit(444)
elseif ua() then
elseif url() then
elseif args() then
elseif cookie() then
elseif PostCheck then
    if method=="POST" then   
            local boundary = get_boundary()
      if boundary then
      local len = string.len
            local sock, err = ngx.req.socket()
          if not sock then
          return
            end
      ngx.req.init_body(128 * 1024)
            sock:settimeout(0)
      local content_length = nil
          content_length=tonumber(ngx.req.get_headers()['content-length'])
          local chunk_size = 4096
            if content_length < chunk_size then
          chunk_size = content_length
      end
            local size = 0
      while size < content_length do
    local data, err, partial = sock:receive(chunk_size)
    data = data or partial
    if not data then
      return
    end
    ngx.req.append_body(data)
          if body(data) then
               return true
            end
    size = size + len(data)
    local m = ngxmatch(data,[[Content-Disposition: form-data;(.+)filename="(.+)\\.(.*)"]],'ijo')
          if m then
                fileExtCheck(m[3])
                filetranslate = true
          else
                if ngxmatch(data,"Content-Disposition:",'isjo') then
                    filetranslate = false
                end
                if filetranslate==false then
                  if body(data) then
                          return true
                    end
                end
          end
    local less = content_length - size
    if less < chunk_size then
      chunk_size = less
    end
   end
   ngx.req.finish_body()
    else
      ngx.req.read_body()
      local args = ngx.req.get_post_args()
      if not args then
        return
      end
      for key, val in pairs(args) do
        if type(val) == "table" then
          if type(val[1]) == "boolean" then
            return
          end
          data=table.concat(val, ", ")
        else
          data=val
        end
        if data and type(data) ~= "boolean" and body(data) then
                      body(key)
        end
      end
    end
    end
else
    return
end

本站优化6:开启nginx的过滤器

最近,本站一直遭到cc攻击骚扰,实在受不了了,这么个小站点,只是记录点自己关注的东西,还天天被练手,有意思吗.......

于是尝试了悬镜防火墙,实测1.9以下总是用的不爽,还占了一部分资源,还不如用nginx自带的过滤器,也算一个小小的防火墙了,至少cc攻击和一些字符串能过滤掉,还能禁ip。

恶意爬虫造成资源占用率100%

很久没有管网站了,今天登陆一下发现cpu占用100%,负载100%,进程里面有几个占用比较大,连接里面有几个ip比较可疑(已经被我屏蔽了):

17 屏蔽IP:[66.249.79.31] 正常 2019-02-05 23:44:49 手动屏蔽 删除
16 屏蔽IP:[66.249.79.27] 正常 2019-02-05 23:44:30 手动屏蔽 删除
15 屏蔽IP:[66.249.79.29] 正常 2019-02-05 23:44:24 手动屏蔽 删除
14 屏蔽IP:[66.249.79.25] 正常 2019-02-05 23:44:16 手动屏蔽 删除
13 屏蔽IP:[66.249.79.19] 正常 2019-02-05 23:44:07 手动屏蔽 删除
12 屏蔽IP:[66.249.79.21] 正常 2019-02-05 23:44:02 手动屏蔽 删除
11 屏蔽IP:[66.249.79.23] 正常 2019-02-05 23:43:18 手动屏蔽

这几个ip百度了一下发现都是谷歌的,我想谷歌不会这么无聊的吧,反正屏蔽后一切恢复正常,我去,我这小站,求各位放过我吧。

mip改造插件增加mip-audio改造

1、加入js。在该插件目录的template目录下的footer.php文件中加入“<script src="https://mipcache.bdstatic.com/static/v1.1/mip-audio.js"></script>”

2、修改i3geek_mip_standard.php,加入如下代码:

function audio($content){
$content=preg_replace('/<(\/audio.*?)>/si','</mip-audio>',$content);
$content=preg_replace("/<(audio.*?)><(.*?)(src)/si","<audio src",$content);

preg_match_all('/<audio (.*?)\>/', $content, $ifs);
if(!is_null($ifs)) {
foreach($ifs[1] as $index => $value){
$mip_audio = str_replace('<audio', '<mip-audio width=800 height=60', $ifs[0][$index]);
$mip_audio = preg_replace('/ srcset=\".*?\"/', '',$mip_audio);
$content = str_replace($ifs[0][$index], $mip_audio, $content);
}
}
return $content;
}

爱上极客的mip改造插件再次报错

今天又发现一篇文章不能通过校验,查看错误内容为:

标签 'source' 只能是标签 '/picture|mip-video|mip-audio/' 的子级标签( 错误代码:06200901)

原文地址:http://findelephant.com/wu-ming-zhi-bei.html

mip改造后地址:http://findelephant.com/wu-ming-zhi-bei.html?mip

因为插入了一个音频文件,需要代码再修改,再看看爱上极客的bbs,好像就没再更新过程序,也没有升级提示,真要命啊,本来想花钱图个方便的.......

是不是考虑自己写一个插件.......

静态缓存页面能使用的WP-PostViews Plus插件

亲测该插件能在静态缓存页面起作用,需要修改主题文件代码,在content.php第22行,把“the_title( '<h1 class="entry-title">', '</h1>' );”修改为“the_title( sprintf( '<h1 class="entry-title">%s', the_views() ),'</h1>');”

主要是加入“the_views()”。

wp主题twentyfifteen首页布局的修改

1、把显示全文改成只显示摘要。在该主题目录下修改index.php第39行为“get_template_part( 'content-search', get_post_format() );”

2、获取第一张图片为缩略图。需要结合wpjam插件使用,在插件中开启该功能,然后找到该主题目录下面的content-search.php,在第22行插入:

<?php

if(wpjam_has_post_thumbnail()){?>

<div class="entry-thumb" align="center">
<a href="<?php the_permalink() ?>" title="<?php the_title_attribute(); ?>"><?php wpjam_post_thumbnail([600,600],$crop=1);?></a>
</div>
<?php } ?>