作者: wind
目前测试可用VPN
https://knmvc.com/s/vyuj11
wf-1000xm4双设备连接固件
2月28日,突然迎来2.0.0固件更新,有了双设备连接,更新后降噪没有变化,同时连接a和b手机,在a手机听歌时,b手机来电可以自动切换,并在通话结束后可以自动切回a手机继续听歌;但是a手机听歌时,b手机播放音乐并不会自动切换到b手机的声音。
关于固件降级的效果,本人在升级到1.6.1固件后,曾使用酷安大神方法降级到1.2.6,并没有发现降噪提升,也就是说根据本人体验,到目前为止的固件的降噪效果都是一样的。调音似乎略有变化,但个人更倾向新的调音,下潜和低音弹性其实新固件更好。
看到一篇笑话:我们为什么要禁止刑讯逼供?
转载自知乎:https://www.zhihu.com/question/266520381/answer/2385205893?utm_id=0
勃列日涅夫和美国总统卡特在瑞士开会,休息时间两个人很无聊,就开始比谁的保镖更忠诚。卡特先来,他把自己的保镖叫进来,推开窗(外面是20层楼)说: “约翰,从这里跳下去!”约翰哭着说:“你怎么能这样呢,总统先生,我还有老婆孩子呐。”卡特被感动了,流着泪说是自己不对,叫约翰走了,然后抡到勃列日涅夫,他也大声叫自己的保镖伊万。“伊万,从这里跳下去!”伊万二话不说就要往下跳,卡特一把抱住他说:“你疯了?跳下去会死的!”伊万一边挣扎着要跳下去一边说:“放开我,混蛋,我还有老婆孩子呐。”
利用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攻击,将相关内容加入白名单就行。
DHA
为记录下这个知识,怕以后找不到了,转载了此文,来源知乎:https://zhuanlan.zhihu.com/p/33275613
毫无悬念:在我们要系统了解对人脑来说什么营养素至为重要时,首先撞见的总是DHA。
DHA含有22个碳原子,其中有6个双键(与亚甲基交替出现)。
在生命体内,这是已知最长的脂肪酸之一(24碳的脂肪酸极为罕见),更是最不饱和的脂肪酸(没有之一)。
起源
要造出长长的多不饱和脂肪酸,需要很多氧气(无氧代谢会用不饱和脂肪酸来接收氢原子,由此产生饱和脂肪酸和反式脂肪酸)——合成DHA中的6个双键就需要6个氧原子,因此在出现氧气之前,地球上应该还没有DHA(至少极少)。
氧气出现后,海洋中的藻类(非植物)终于能用氧气来制造DHA了——这种“复杂的”脂类使得细胞能用来构建复杂的细胞结构,比如内质网、核膜、线粒体内的电子传递链,以及带有各种受体、转运蛋白、抗氧化酶的(流动性极佳的)细胞膜——细胞结构由此开始急剧复杂化。
细胞膜中嵌入的多不饱和脂肪酸,主要是AA、dGLA、EPA、DHA,它们一般位于甘油磷脂上的sn-2位置上。
复杂的结构(尤其是复杂的细胞膜)带来了复杂的功能,比如“信息处理”——DHA让动物们开始长出眼睛(视网膜的电活动需要DHA)和脑子——越来越“高级”的生命体开始涌现,头足动物、鱼类、两栖类、爬行类、鸟类和兽类陆续登场,而DHA一直都是它们的视网膜细胞、神经细胞内不可替代的油脂。
因此动物的眼和脑是DHA最集中的地方,尤其是脑内的灰质,更尤其是神经元之间形成连接的地方,最需要复杂的细胞膜结构的地方,也是生命体内的化学信号和电信号最集中的地方——突触。
灰质以多不饱和脂肪酸为主,其中DHA多于AA;而白质中则以单不饱和脂肪酸为主,AA多于DHA。
因此,当古人类终于来到海边采集“潮汐带”食物,从而能稳定、大量摄入DHA时,其脑内的灰质部分也急剧膨胀,直到自诩为“最高等生命”的智人出现。
具体功能
漫长的演化史中,DHA的功能越来越复杂(背后是生命发展出了越来越多样的DHA受体);具体来说,这种古老的脂类能够:
影响生命的基础代谢率。通过对兽类(哺乳动物)和鸟类的脑、心、肾组织的研究,发现细胞膜中的DHA水平越高,其中的钠钾ATP酶(运输钠钾离子通过细胞膜,维持细胞内外的钠钾平衡,其能耗往往占整个生命体基础代谢率的1/5)的活性就越高(呈线性相关)——动物的脑是这种酶活性最高的地方,从而也是最需要(也最富含)DHA的地方。
钠钾ATP酶的能耗占整个脑部能耗的3/5!因为要不断发射电信号(靠改变钠钾离子的分布来实现)的神经元,极其依赖于及时维持的钠钾平衡。
影响细胞通讯。通过增强细胞膜上的G蛋白的可溶性,DHA能够影响G蛋白偶联受体的行为,从而间接影响各种细胞信号。比如,视网膜内的细胞膜上的视紫质就是一种G蛋白,DHA使其能够快速地接收光线(在此过程中DHA会与光受体分离,然后再被回收)。
消除体内炎症。DHA可以直接抑制NF-κB(细胞核转录因子κB)——这是免疫细胞(B细胞、T细胞)中的一种蛋白质,对氧化压力非常敏感——比如当活性氧簇水平升高时,或者其他炎症信号分子(比如主要由AA氧化成的类花生酸)出现时,它就会被激活,然后进入细胞核,上调许多促炎基因(比如白介素2、白介素6、白介素8、肿瘤坏死因子)的表达。而DHA可以直接抑制这个炎症的源头,从而降低全身的炎症水平。
DHA还可以间接抑制NF-κB。比如通过影响G蛋白偶联受体,减少磷脂酶A2的释放,从而减少类花生酸的合成;还有:
在局部炎症中,DHA(还有EPA)会从磷脂中被释放,转化成消炎的信号分子:消退素,它能下调NF-κB,从炎症部位驱除嗜中性粒细胞;和保护素(尤其是神经保护素),它主要出现在神经细胞、星形胶质细胞、循环组织和肺组织中,能促进神经再生,减少白细胞渗透,减少促炎和促进细胞凋亡的信号分子,从而保护神经细胞和视网膜细胞。
DHA还能上调细胞内的谷胱甘肽水平,进而降低细胞内的炎症水平。
促进神经发生。通过提升脑源性神经营养因子的水平,DHA能让脑内产生新的神经细胞和新的神经连接,并维持现有神经细胞的良好状态。
参与神经信号传递、形成记忆。当神经信号出现在突触时,此处的DHA(还有AA)会被(从磷脂中)释放进细胞液中,其中一部分转化成二级信号分子(类22碳酸——AA的话则是类花生酸),极少量被燃烧掉(β氧化),绝大部分则被磷脂迅速重新收纳——细胞膜借此过程得以重组,从而能强化神经通道,形成新的记忆。
改变基因表达、调节激素水平。DHA(还有EPA)会通过影响PPARγ、RXR、NF-κB来改变基因表达,从而增强生命体的整体适应能力、抗压能力;DHA水平还相关于瘦素水平和激素平衡。
将甲状腺素运输进脑。DHA参与合成甲状腺素转运蛋白,后者可以让甲状腺素穿过血脑屏障,从而让脑获得另一种对它至为紧要的营养素——碘。
不可替代
生命体如此需要DHA,一般认为,是因为作为最不饱和的脂肪酸, DHA的6个双键可以让其分子呈微螺旋结构,从而能让细胞膜有最高的流动性。
但这似乎并非DHA最擅长的:DHA在低于零下44℃时就会凝固,相比来说,AA要到零下50℃才会凝固,EPA更要到零下54℃。
是的,DHA有着独特的分子形态:很长,很多双键。
不过DPA也是这样:同样有22个碳,只是比DHA少了一个双键(根据缺少的双键的位置,有ω-3和ω-6两种DPA);从化学角度看,这种差异本不会造成迥异的分子特性。
何况在陆地食物链中,DHA非常少,相比之下DPA却丰富多了——生命为何要去依赖一种稀有的,而不去(试图通过进化)开发利用另一种富庶的资源?毕竟只差了一个双键而已……
我们看到,虽然在大型陆兽(比如大象)的身体组织内有大量的DPA;但是在其脑内,在其中的神经细胞膜内,却仍然谨守着可怜的那一丁点DHA……对DHA的“愚忠”大大限制了陆兽的相对脑容量(其脑容量相对于体型呈指数下降)。
为了理解这种愚忠,也许需要我们深入到量子生物学中(这是一个人类大体上还在摸黑的、全新的知识领域):比如6个双键的结构可能让π电子云出现极化,甚至能在双键之间传输,这使DHA能有奇特的、独一无二的电学特性;比如6个双键可能允许神经微管的伽马相干(γ coherence)……
不过即使还不能完全理解DHA的不可替代性,我们只需要知道这点也就够了:
登上陆地后3亿多年的演化,也没能让陆地动物摆脱对DHA的依赖。
如果有意地将动物体内的DHA换成DPA,其组织功能就会明显恶化。
难以合成
合成DHA似乎成了海藻们的绝技,陆地植物完全不解其中奥妙:后者擅长的是制造很短(18个碳)的多不饱和脂肪酸,尤以ω-6的LA为主,偶尔有少量的ALA。
淡水藻类由于会进行很多无氧代谢(产生饱和脂肪酸和反式脂肪酸),能制造的DHA也非常少。
是的,ALA与DHA一样都是光荣的ω-3,理论上是可以转化为后者的。于是对DHA不离不弃的陆生动物被迫接手了这个转化大业(主要在动物的营养中心——肝脏内进行)。
但这个转化的过程(ALA > EPA > DPA > DHA)漫长而繁琐,其中一些步骤的效率非常低,比如给ALA添加两个双键(“去饱和”),比如将EPA延长为DPA,但效率最低的还是给DPA再添加最后一个双键的过程——要完成这神奇一跃所需的“Δ6去饱和酶”非常少……所以转化往往都停滞在了DPA上——这就是陆兽们体内会有大量DPA的原因。
现代人饮食中大量的ω-6尤其是其中的LA,还会跟ALA竞争去饱和酶,更是大大拉低了ALA本就可怜的转化效率。
于是我们看到,虽然在陆兽的肝脏内有大量的ALA,少量的EPA,不少的DPA,但DHA却仍然稀有。
海豚与非洲水牛的肝脏中,ALA(18:3)、EPA(20:5)、DPA(22:5)、DHA(22:6)的比例。
对于成年人类来说,大量补充ALA虽然可以显著提高体内的EPA和DPA水平,但其(血液和母乳中的)DHA水平几乎纹丝不动。
母乳中的DHA水平对饮食中的DHA含量非常敏感。
即使在Δ6去饱和酶最为活跃的地方——人类婴儿的身体中,DHA的合成效率仍然不够理想:在饮食中只有ALA、缺少DHA的情况下,婴儿体内聚集DHA的速度仍然只有母乳喂养的婴儿的一半。
相比于只摄入ALA,让婴儿期的灵长类和人类直接摄入DHA能显著改善其视网膜功能。
随着年龄增长,人体内的Δ6去饱和酶的活性会急剧衰减。
转化速度慢,成功率低:植物的ω-3并不能给整个陆地食物链注满“灵油”。
于是我们看到,陆兽们的脑量完全无法跟上其体量的发展;相比之下,处在海洋食物链中的海兽就不受这种局限(比如斑马只有350g的脑,与其体重相当的海豚的脑则有1800g)。
DHA就这样成了大地上最为珍稀的油脂——只是一个双键,让DPA和陆兽们望洋兴叹。
我们需要DHA
人类的相对脑容量,却远远摆脱了这个禁锢。
陆兽的相对脑容量随着体型增大急剧下降——除了人类。
于是人类对DHA的需求量,也远远超出了陆地食物链的供给能力。不仅人类婴儿为了快速发育脑部,需要大量的DHA(好在最需要DHA的物种在最需要DHA的时候还有一定的自给自足能力);成年人为了维持脑的健康状态,也需要持续的DHA供应。
固然,人体能够非常有效地保存DHA,比如在视网膜和神经突触的电化学过程中不断被释放的DHA,绝大多数都会被迅速回收;细胞本身也有一定的维护机制,可以保护DHA少受氧化,并能恢复一些受损的DHA。(这个机制需要褪黑素,因此现代生活中的蓝光还会加速DHA的流失。)
但DHA毕竟还在不断损失着,即使很慢——据估计,脑内DHA的半衰期大约是2.5年。
再加上,在DHA短缺的情况下,人体还会从其他部位调拨DHA来优先保证脑的供应。于是脑很可能在很长一段时间内不会有缺乏DHA的迹象。
但是身体其他部位的情况就不容乐观了(我们在上面已经看到,DHA的工作远远不止限于脑内):缺乏DHA会导致基础代谢率下降、炎症水平上升、激素失衡、瘦素抵抗……
当减肥困难、生理期紊乱、低密度脂蛋白水平过高时,都可以考虑是否有DHA摄入过少的可能……
视网膜内的DHA匮乏,还会逐渐导致黄斑退化……
当然,长期缺乏DHA最终还是会影响到脑部——星形胶质细胞受损,神经细胞不能正常工作……然后思维活力不足,记忆力下降,甚至脑萎缩……
现代智人的平均脑容量,已经从10万年前的1490g下降到了1360g……DHA的普遍匮乏与之会否也有相关呢?(或许“现代人比原始人更聪明”,但也主要是因为“软件”而非“硬件”。)
关于DHA对各种神经退行性疾病的治疗作用,会有越来越多的相关研究。
我认为,为了让整个身体满状态运转,我们每天需要摄入至少2g的DHA。
这是我根据人类进化史做出的推测……是的,这个推荐量比可能在其他地方见到的(一般是几百毫克)要高多了。
怎样补充
为了补充DHA,我们不能依靠植物油里所谓的ω-3——ALA。
除了转化速度慢、成功率低(尤其是在成年人体内),ALA的氧化速度也非常快:提取出来后,每天甚至能氧化60%!所以那些所谓“富含ω-3”的植物油(比如亚麻籽油、夏威夷果油、核桃油),反而应该是我们躲之唯恐不及的……
即使从完整的食物中摄取的ALA,在进入人体后也主要是被用来当燃料了,或者被合成为饱和脂肪酸、胆固醇。
在饮食中的DHA充足时,进入脑中的ALA(多不饱和脂肪酸可以轻易穿过血脑屏障)几乎有99%都会被燃烧(β氧化)掉。
ALA作为“必需脂肪酸”的地位正在被质疑,很可能:我们需要的只是其衍生物EPA和DHA,而完全不需要ALA本身。
为了补充DHA,我们需要直接摄入DHA。
植物不行,海藻怎样呢?
很可惜:作为地球上DHA的究极来源,海藻本身所含的DHA却非常少——一般在0.1mg/100g以下。这样即使每天只需补充500mg的DHA,摄入50公斤的海藻也还是不够。
那么从海藻中提取出来的DHA补剂呢?或者鱼油呢?
虽然DHA的氧化率比ALA要小多了,但每天也有5%左右——提取出来后,要经过多少天才能被我们吃下去呢?我们吃下去的,还能有多少完好的呢?
还是得吃食物本身:食物里的DHA不仅要稳定得多(由于各种抗氧化机制(维生素E、谷胱甘肽过氧化酶、碘)的存在),而且也好用得多——动物体内的DHA主要存在于甘油磷脂的sn-2位置上,这样最容易被身体吸收和利用。
应该吃什么动物呢?
虽然陆地动物能够合成一点DHA,但效率毕竟低下,那些无论肥瘦的畜肉禽肉,其中所含的DHA都几乎可以无视——再“草饲”也不行;只有其脑髓还算有可以看的DHA含量——只是要达到推荐摄入量,每天都要吃上400g左右……似乎并不是一个可以长期坚持的吃法。
淡水鱼里的“鲇形目”是一个例外,以后会说。
好在:海藻合成的DHA,最终都富集到了海洋动物们的脂肪内。最好的补充DHA的方法,就是吃各种海鲜:海贝、海鱼、海蟹、海虾……每100g的贻贝肉或牡蛎肉就含有250mg以上的DHA,更不用提秋刀鱼、三文鱼、带鱼、鲭鱼这些“油鱼”,每100g肉往往都有超过1g的DHA。
目前已知含DHA最多的应该是安康鱼肝——每100g含有3.6g。(鳕鱼肝油不算食物,也不推荐。)
所以:每周至少吃3斤油鱼(或再辅以其他海鲜),才好满足我们的整个身体,尤其是脑对这“灵油”的需求。
大约5~8亿年前,第一个脑诞生于大海中;数亿万年后,智慧终究还要回到故乡。
禁用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。