更换WordPress网站域名的方法

我们以手头的演示网站为例,介绍一下如何将WordPress网站的域名从旧域名 www.mydomain.com 更换为新域名 www.newdomain.com 。

第一步,开始之前,请先做好网站的备份,备份好网站数据库和网站文件。尤其是数据库,一定要做好备份,以防操作过程中出现错误,我们可以使用备份的数据库重新进行操作。

第二步,将新域名做好解析和绑定操作。解析新域名,就是将域名指向服务器的IP地址,通常在域名商那里进行操作;绑定新域名,通常在空间商那里进行操作,就是在服务器上添加新域名,并确保网站目录和旧域名的网站目录一致。

完成以上两步之后,需要确认新域名生效之后,再继续进行以下操作。新域名设置解析后,通常需要一段时间才能传递到各地网络,各地生效时间并不一致,通常需要几分钟或者几个小时,最多不会超过48小时。你可以使用ping命令来检查,来查看新域名是否生效。如果ping出来的ip地址是刚刚设置的ip,那么解析就生效了。

新域名生效之后,这个时候在浏览器中输入新域名和旧域名,都可以打开原来的网站。如果旧域名已经失效,比如说已经过期,或者已经解析到其他地方等,那么网站虽然可以打开,但网页看起来会比较乱;这是因为网页无法正常加载WordPress主题的样式表。

第三步,登录主机管理系统,进入phpmyadmin,选择WordPress网站所使用的数据库。如果你不确定WordPress使用的是哪一个数据库,可以查看WordPress目录下的wp-config.php配置文件,查看其中的 DB_NAME 设置。

选中该数据库之后,点击SQL,输入以下代码:

UPDATE wp_options SET option_value = replace(option_value,'www.mydomain.com','www.newdomain.com') ;

UPDATE wp_posts SET post_content = replace(post_content, 'www.mydomain.com','www.newdomain.com') ;

UPDATE wp_comments SET comment_content = replace(comment_content, 'www.mydomain.com', 'www.newdomain.com') ;

UPDATE wp_comments SET comment_author_url = replace(comment_author_url, 'www.mydomain.com', 'www.newdomain.com') ;

以上代码中,www.mydomain.com 代表原来的域名,www.newdomain.com 代表新域名。域名一定要输入完整;如果你使用类似 blog.newdomain.com 这样的二级域名,也是可以的,只要输入完整域名就可以了。

然后点击右下角的【执行】按钮,就可以了。phpmyadmin会返回结果,告诉你每行命令修改了多少处地方。这样,我们就将WordPress的域名完美地切换到新的域名了。

与直接在WordPress的管理后台修改域名相比,今天介绍的这个办法有两个优点:

  1. 即便旧域名已经失效了,也可以更换新域名;因为整个操作过程中,根本不需要登陆WordPress的管理后台。

  2. 更换比较彻底,不光更换了网站的域名,连文章内部的链接,图片和音视频等媒体文件的地址、链接,以及评论中的链接等,都一起进行了更换。

因此,通过以上操作,可以比较完美地更换WordPress网站域名。现在,再使用新域名去访问你的WordPress网站试试吧。

wordpress开启Redis扩展教程

本教程中使用到的是宝塔面板(宝塔面板,小白建站的不二之选)Wordpress站点如果时间久了,流量大了,文章多了,前台后台都会变得龟速!

利用Redis将WordPress页面直接缓存在服务器的内存中,这样在避免了PHP重复执行操作的同时,内存的极速响应能够最大限度地提升Wordpress页面的访问速度,实际测试发现页面执行时间可以降低到0.00X秒级别,比没有使用Redis缓存提升几倍甚至十几倍以上。

利用宝塔面板非常简单的就能安装配置成功!

1、首先我们需要进入宝塔面板安装Redis扩展

未分类

2、下载我们要用到的PHP文件

  • PHP文件下载

https://www.ddblog.cc/wp-content/themes/begin/inc/go.php?url=https://page22.ctfile.com/fs/12214022-213374766

  • 下载解压以后我们会得到predis.php和wp-index-redis.php两个文件

  • 上传这两个文件到Wordpress的根目录

3、配置修改及注意事项

  • 如果你想在页面上看到脚本执行时间和缓存加载时间

请打开wp-index-redis.php文件把

// change vars here
$cf = 0;                // set to 1 if you are using cloudflare
$debug = 0;             // set to 1 if you wish to see execution time and cache actions

修改为

// change vars here
$cf = 0;                // set to 1 if you are using cloudflare
$debug = 1;             // set to 1 if you wish to see execution time and cache actions

也就是把$debug = 0;修改为$debug = 1;

  • 如果你使用的是nginx,需要原来的根目录的index.php修改为为任意其它名字,把wp-index-redis.php重命名为index.php

  • 如果你使用的是Apache,则需要把.htaccess中出现的index.php替换成wp-index-redis.php,我命名的是下面图片的名字。

未分类

所有的操作完成后,你就可以刷新一下Wordpress页面,查看Redis缓存效果了

  • 如果开启了缓存插件或cdn请先关闭才能看到效果

删除某一个页面的缓存:发表评论、按下F5刷新、在URL后面加上?r=y回车。

删除整站页面缓存:登录到Wordpress后台,在任意URL后面加上?r=y回车。

wireshark使用教程及过滤语法总结

wireshark介绍

wireshark的官方下载网站: http://www.wireshark.org/

wireshark是非常流行的网络封包分析软件,功能十分强大。可以截取各种网络封包,显示网络封包的详细信息。

wireshark是开源软件,可以放心使用。

Wireshark是一款高效免费的网络抓包分析工具。它可以捕获并描述网线当中的数据,如同使用万用表测量电压一样直观地显示出来。在网络分析软件领域,大多数软件要么晦涩难懂要么价格昂贵,Wireshark改变了这样的局面,它的最大特点就是免费、开源和多平台支持。

Wireshark几乎可以运行于所有流行的操作平台,如MS Windows、Mac OS、Linux、FreeBSD、HP-UX、NetBSD、Solaris/i386、Solaris/sparc等等。尽管Wireshark可以在很多操作平台使用,但它支持的传输媒介主要是Ethernet。只有Linux平台下Wireshark支持802.11及Token Ring、FDDI和ATM。

Wireshark能够对大部分局域网协议进行解析,具有界面简单、操作方便、实时显示捕获数据的优点。但Wireshark并不具有分析功能,当一个网络发生异常的时候,Wireshark只会记录数据,它仅仅是一个测量工具,并不能操作网络,不发送数据包或者做其它的主动动作。

使用wireshark的人必须了解网络协议,否则就看不懂wireshark了。

Wireshark不能做的

为了安全考虑,wireshark只能查看封包,而不能修改封包的内容,或者发送封包。

什么人会用到wireshark

  1. 网络管理员会使用wireshark来检查网络问题

  2. 软件测试工程师使用wireshark抓包,来分析自己测试的软件

  3. 从事socket编程的工程师会用wireshark来调试

  4. 听说,华为,中兴的大部分工程师都会用到wireshark。

总之跟网络相关的东西,都可能会用到wireshark.

wireshark 开始抓包

wireshark是捕获机器上的某一块网卡的网络包,当你的机器上有多块网卡的时候,你需要选择一个网卡。

点击Caputre->Interfaces.. 出现下面对话框,选择正确的网卡。然后点击”Start”按钮, 开始抓包

未分类

未分类

Wireshark 窗口介绍

未分类

WireShark 主要分为这几个界面

  1. Display Filter(显示过滤器),用于过滤
  2. Packet List Pane(封包列表),显示捕获到的封包,有源地址和目标地址,端口号。颜色不同,代表
  3. Packet Details Pane(封包详细信息), 显示封包中的字段
  4. Dissector Pane(16进制数据)
  5. Miscellanous(地址栏,杂项)

Wireshark 显示过滤

未分类

使用过滤是非常重要的, 初学者使用wireshark时,将会得到大量的冗余信息,在几千甚至几万条记录中,以至于很难找到自己需要的部分。搞得晕头转向。

过滤器会帮助我们在大量的数据中迅速找到我们需要的信息。

过滤器有两种,

  • 一种是显示过滤器,就是主界面上那个,用来在捕获的记录中找到所需要的记录

  • 一种是捕获过滤器,用来过滤捕获的封包,以免捕获太多的记录。 在Capture -> Capture Filters 中设置

保存过滤

在Filter栏上,填好Filter的表达式后,点击Save按钮, 取个名字。比如”Filter 102″,

Filter栏上就多了个”Filter 102″ 的按钮。

过滤器的区别

  • 捕捉过滤器(CaptureFilters):用于决定将什么样的信息记录在捕捉结果中。需要在开始捕捉前设置。
  • 显示过滤器(DisplayFilters):在捕捉结果中进行详细查找。他们可以在得到捕捉结果后随意修改。
  • 那么我应该使用哪一种过滤器呢?
  • 两种过滤器的目的是不同的。
  • 捕捉过滤器是数据经过的第一层过滤器,它用于控制捕捉数据的数量,以避免产生过大的日志文件。
  • 显示过滤器是一种更为强大(复杂)的过滤器。它允许您在日志文件中迅速准确地找到所需要的记录。
  • 两种过滤器使用的语法是完全不同的。

捕捉过滤器

语法:Protocol, Direction, Host(s), Value, Logical, Operations, Other expression

例子: tcp, dst, 10.1.1.180, and, tcp dst 10.2.2.2 3128

Protocol(协议):

可能的值: ether, fddi, ip, arp, rarp, decnet, lat, sca, moprc, mopdl, tcp and udp.

如果没有特别指明是什么协议,则默认使用所有支持的协议。

Direction(方向):

可能的值: src, dst, src and dst, src or dst

如果没有特别指明来源或目的地,则默认使用 “src or dst” 作为关键字。

例如,”host 10.2.2.2″与”src or dst host 10.2.2.2″是一样的。

Host(s):

可能的值: net, port, host, portrange.

如果没有指定此值,则默认使用”host”关键字。

例如,”src 10.1.1.1″与”src host 10.1.1.1″相同。

Logical Operations(逻辑运算):

可能的值:not, and, or.

否(“not”)具有最高的优先级。或(“or”)和与(“and”)具有相同的优先级,运算时从左至右进行。

例如

“not tcp port 3128 and tcp port 23″与”(not tcp port 3128) and tcp port 23″相同。

“not tcp port 3128 and tcp port 23″与”not (tcp port 3128 and tcp port 23)”不同。

过滤表达式的规则

表达式规则

1、协议过滤

比如TCP,只显示TCP协议。

2、IP 过滤

比如

ip.src ==192.168.1.102 显示源地址为192.168.1.102,
ip.dst==192.168.1.102, 目标地址为192.168.1.102

3、端口过滤

tcp.port ==80,  端口为80的

tcp.srcport == 80,  只显示TCP协议的愿端口为80的。

4、Http模式过滤

http.request.method=="GET",   只显示HTTP GET方法的。

5、逻辑运算符为 AND/ OR

常用的过滤表达式

过滤表达式                                        用途

http                                             只查看HTTP协议的记录
ip.src ==192.168.1.102 or ip.dst==192.168.1.102  源地址或者目标地址是192.168.1.102
eth.addr== 00:11:22:33:44:55                     //过滤目标或源地址是00:11:22:33:44:55的数据包
tcp dst port 3128                                显示目的TCP端口为3128的封包。
ip src host 10.1.1.1                             显示来源IP地址为10.1.1.1的封包。

host 10.1.2.3                                    显示目的或来源IP地址为10.1.2.3的封包。
src portrange 2000-2500                          显示来源为UDP或TCP,并且端口号在2000至2500范围内的封包。


src host 10.7.2.12 and not dst net 10.200.0.0/16 显示来源IP地址为10.7.2.12,但目的地不是10.200.0.0/16的封包。

(src host 10.4.1.12 or src net 10.6.0.0/16) and tcp dst portrange 200-10000 and dst net 10.0.0.0/8  
                                                 显示来源IP为10.4.1.12或者来源网络为10.6.0.0/16,目的地TCP端口号在200至10000之间,并且目的位于网络 10.0.0.0/8内的所有封包。

src net 192.168.0.0/24

src net 192.168.0.0 mask 255.255.255.0           显示来源IP地址为10.1.1.1的封包。

注意事项:

当使用关键字作为值时,需使用反斜杠“/”。

“ether proto /ip” (与关键字”ip”相同).

这样写将会以IP协议作为目标。

“ip proto /icmp” (与关键字”icmp”相同).

这样写将会以ping工具常用的icmp作为目标。

可以在”ip”或”ether”后面使用”multicast”及”broadcast”关键字。

当您想排除广播请求时,”no broadcast”就会非常有用。

Protocol(协议):

您可以使用大量位于OSI模型第2至7层的协议。点击”Expression…”按钮后,您可以看到它们。

比如:IP,TCP,DNS,SSH

String1, String2 (可选项):

协议的子类。

点击相关父类旁的”+”号,然后选择其子类。

Comparison operators (比较运算符):

可以使用6种比较运算符:

英文写法:   C语言写法:  含义:
eq          ==          等于
ne          !=          不等于
gt          >           大于
lt          <           小于
ge          >=          大于等于
le          <=          小于等于

Logical expressions(逻辑运算符):

英文写法:   C语言写法:  含义:
and         &&          逻辑与
or          ||          逻辑或
xor         ^^          逻辑异或
not         !           逻辑非

显示过滤器

语法: Protocol, String 1, String 2, Comparison operator, Value, Logical Operations, Other expression

例子: ftp, passive, ip, ==, 10.2.3.4, xor, icmp.type

例子:

snmp || dns || icmp                         显示SNMP或DNS或ICMP封包。
ip.addr == 10.1.1.1                         显示来源或目的IP地址为10.1.1.1的封包。
ip.src != 10.1.2.3 or ip.dst != 10.4.5.6    显示来源不为10.1.2.3或者目的不为10.4.5.6的封包。

换句话说,显示的封包将会为:

  • 来源IP:除了10.1.2.3以外任意;目的IP:任意
    以及
  • 来源IP:任意;目的IP:除了10.4.5.6以外任意
ip.src != 10.1.2.3 and ip.dst != 10.4.5.6   显示来源不为10.1.2.3并且目的IP不为10.4.5.6的封包。

换句话说,显示的封包将会为:

  • 来源IP:除了10.1.2.3以外任意;同时须满足,目的IP:除了10.4.5.6以外任意
tcp.port == 25          显示来源或目的TCP端口号为25的封包。
tcp.dstport == 25       显示目的TCP端口号为25的封包。
tcp.flags               显示包含TCP标志的封包。
tcp.flags.syn == 0×02   显示包含TCP SYN标志的封包。

如果过滤器的语法是正确的,表达式的背景呈绿色。如果呈红色,说明表达式有误。

wireshark过滤匹配表达式实例

匹配过滤HTTP的请求URI中含有”.gif”字符串,并且以.gif结尾(4个字节)的http请求数据包($是正则表达式中的结尾表示符)

http.request.uri matches ".gif$" 

注意区别:http.request.uri contains “.gif$” 与此不同,contains是包含字符串”.gif$”(5个字节)。匹配过滤HTTP的请求URI中含有”.gif$”字符串的http请求数据包(这里$是字符,不是结尾符)

搜索过滤MAC地址前3个字节是0x001e4f的数据包。

eth.addr[0:3]==00:1e:4f 

搜索按条件过滤udp的数据段payload(数字8是表示udp头部有8个字节,数据部分从第9个字节开始udp[8:])

udp[8]==14                        (14是十六进制0x14)匹配payload第一个字节0x14的UDP数据包

udp[8:2]==14:05                    可以udp[8:2]==1405,且只支持2个字节连续,三个以上须使用冒号:分隔表示十六进制。 (相当于 udp[8]==14 and udp[9]==05,1405是0x1405)

udp[8:3]==22:00:f7                 但是不可以udp[8:3]==2200f7

udp[8:4]==00:04:00:2a,            匹配payload的前4个字节0x0004002a

而udp contains 7c:7c:7d:7d         匹配payload中含有0x7c7c7d7d的UDP数据包,不一定是从第一字节匹配。

udp[8:4] matches "\x14\x05\x07\x18"

udp[8:] matches "^\x14\x05\x07\x18\x14"

搜索按条件过滤tcp的数据段payload(数字20是表示tcp头部有20个字节,数据部分从第21个字节开始tcp[20:])

tcp[20:] matches "^GET [ -~]*HTTP/1.1\x0d\x0a"

等同http matches "^GET [ -~]*HTTP/1.1\x0d\x0a"


tcp[20:] matches "^GET (.*?)HTTP/1.1\x0d\x0a"

tcp[20:] matches "^GET (.*?)HTTP/1.1\x0d\x0a[\x00-\xff]*Host: (.*?)pplive(.*?)\x0d\x0a"

tcp[20:] matches "^GET (.*?)HTTP/1.1\x0d\x0a[\x00-\xff]*Host: "

tcp[20:] matches "^POST / HTTP/1.1\x0d\x0a[\x00-\xff]*\x0d\x0aConnection: Keep-Alive\x0d\x0a\x0d\x0a"

检测SMB头的smb标记,指明smb标记从tcp头部第24byte的位置开始匹配。

tcp[24:4] == ff:53:4d:42

检测SMB头的smb标记,tcp的数据包含十六进制ff:53:4d:42,从tcp头部开始搜索此数据。

tcp contains ff:53:4d:42

tcp matches "\xff\x53\x4d\x42"

检测tcp含有十六进制01:bd,从tcp头部开始搜索此数据。

tcp matches "\x01\xbd"

检测MS08067的RPC请求路径

tcp[179:13] == 00:5c:00:2e:00:2e:00:5c:00:2e:00:2e:00
                 .     .          .     .

封包列表(Packet List Pane)

封包列表的面板中显示,编号,时间戳,源地址,目标地址,协议,长度,以及封包信息。 你可以看到不同的协议用了不同的颜色显示。

你也可以修改这些显示颜色的规则, View ->Coloring Rules.

未分类

封包详细信息 (Packet Details Pane)

这个面板是我们最重要的,用来查看协议中的每一个字段。

各行信息分别为

Frame:                          物理层的数据帧概况

Ethernet II:                    数据链路层以太网帧头部信息

Internet Protocol Version 4:    互联网层IP包头部信息

Transmission Control Protocol:  传输层T的数据段头部信息,此处是TCP

Hypertext Transfer Protocol:    应用层的信息,此处是HTTP协议

未分类

TCP包的具体内容

从下图可以看到wireshark捕获到的TCP包中的每个字段。

未分类

实例分析TCP三次握手过程

看到这, 基本上对wireshak有了初步了解, 现在我们看一个TCP三次握手的实例

未分类

这图我都看过很多遍了, 这次我们用wireshark实际分析下三次握手的过程。

打开wireshark, 打开浏览器输入 http://www.cnblogs.com/tankxiao

在wireshark中输入http过滤, 然后选中GET /tankxiao HTTP/1.1的那条记录,右键然后点击”Follow TCP Stream”,

这样做的目的是为了得到与浏览器打开网站相关的数据包,将得到如下图

未分类

图中可以看到wireshark截获到了三次握手的三个数据包。第四个包才是HTTP的, 这说明HTTP的确是使用TCP建立连接的。

第一次握手数据包

客户端发送一个TCP,标志位为SYN,序列号为0, 代表客户端请求建立连接。 如下图

未分类

第二次握手的数据包

服务器发回确认包, 标志位为 SYN,ACK. 将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即0+1=1, 如下图

未分类

第三次握手的数据包

客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1, 如下图:

未分类

就这样通过了TCP三次握手,建立了连接。

通过克隆虚拟机磁盘实现快速迁移VirtualBox虚拟机

Windos server上使用VirualBox迁移虚拟机时,可以使用自带的导入导出功能,但是当虚拟机比较大超过几十个G的容量,就会特别慢。一般比较快捷的方式是直接克隆虚拟机磁盘,然后复制虚拟机磁盘到新的机器上,创建一个新的虚拟机,选中克隆的磁盘。

查看虚拟机虚拟磁盘位置:

克隆磁盘命令,使用安装目录下的VBoxManage.exe执行克隆,命令行执行:

C:>F:VirtualBoxVBoxManage clonehd F:win2008_1win2008_1-disk1.vdi F:VM-BACK
win2008_1-247.vdi

克隆完成后会重新生成一个新的UUID,如果直接拷贝原来的虚拟磁盘启动会报错。

在新的虚拟机中创建此虚拟机:

使用克隆的磁盘启动:

启动虚拟机即可,第一次加载会比较慢。克隆虚拟机也是使用相同的方式。

Varnish配置示例说明

Varnish与一般服务器软件类似,分为master(management)进程和child(worker,主要做cache的工作)进程。master进程读入命令,进行一些初始化,然后fork并监控child进程。child进程分配若干线程进行工作,主要包括一些管理线程和很多woker线程。

varnish架构图:

未分类

varnish的配置示例:

1、主配置文件的修改:

varnish作为web服务的反向代理服务器,要监听在80端口,因此要修改配置文件:

vim /etc/varnish/varnish.params

未分类

记得创建你所指定的路径:mkdir /data/varnish/cache

并将属主属组修改为varnish:chown -R varnish:varnish /data/varnish/cache

2、配置后端主机:

vim /etc/varnish/default.vcl

未分类

后端主机安装httpd作为测试

重读default.vcl文件:varnsih_reload_vcl 或者通过交互式方式重载配置varnish配置:varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082

命令行下:

vcl.load <configname> <filename> 重载配置文件default.vcl(filename),并将其命名
vcl.use <configname>使用新生成的配置

网页通过http访问此varnish主机得到:

未分类

说明后端主机配置成功

3、VCL: ”域“专有类型的配置语言

VCL有多个状态引擎,状态之间存在相关性,但状态引擎彼此间互相隔离;每个状态引擎可使用return(x)指明关联至哪个下一级引擎;每个状态引擎对应于vcl文件中的一个配置段,即为subroutine

变量类型:

内建变量:

  • req.*:request,表示由客户端发来的请求报文相关;
  • bereq.*:由varnish发往BE主机的httpd请求相关;
  • resp.*:由varnish响应给client相关;
  • obj.*:存储在缓存空间中的缓存对象的属性;只读;

常用变量:

  • bereq.*, req.*:
  • bereq.http.HEADERS
  • bereq.request:请求方法;
  • bereq.url:请求的url;
  • bereq.proto:请求的协议版本;
  • bereq.backend:指明要调用的后端主机;
  • req.http.Cookie:客户端的请求报文中Cookie首部的值;
  • req.http.User-Agent ~ “chrome”
  • beresp.*, resp.*:
  • beresp.http.HEADERS
  • beresp.status:响应的状态码;
  • reresp.proto:协议版本;
  • beresp.backend.name:BE主机的主机名;
  • beresp.ttl:BE主机响应的内容的余下的可缓存时长;
  • obj.*
  • obj.hits:此对象从缓存中命中的次数 >1 表示命中;
  • obj.ttl:对象的ttl值
  • server.*
  • server.ip
  • server.hostname
  • client.*
  • client.ip

介绍几个VCL配置的实例:

(1)添加报文首部:vim default.vcl

obj.hits是内建变量,用于保存某缓存项的从缓存中命中的次数;

在sub vcl_deliver中添加

if (obj.hits>0) {

          set resp.http.X-Cache = “HIT via ” + server.ip;
   } else {
          set resp.http.X-Cache = “MISS via ” + server.ip;
   }

在交互式命令行下手动装载配置,并使用:

vcl.load  test default.vcl

vcl_use test

测试:

未分类

刷新网页,再次访问,会出现“HIT via….”字样

(2)强制对某类资源的请求不检查缓存,在请求报文中包含以/login|admin 为首的不查缓存,直接送到backend(后端服务器):

sub   vcl_recv {
       if (req.url ~ “(?i)^/(login|admin)”) {
          return(pass);
       }
    }

禁止以curl方式访问:

sub   vcl_recv {
       if (req.http.User-Agent ~ “(?i)^/curl”) {
          return(synth(403));
       }
    }

测试:

未分类

(3)对于特定类型的资源,例如公开的图片等,取消其私有标识(cookie),并强行设定其可以由varnish缓存的时长;

sub  vcl_backend_response {

     if (beresp.http.cache-control !~ “s-maxage”) {
        if (bereq.url ~ “(?i).(jpg|jpeg|png|gif|css|js)$”) {
           unset beresp.http.Set-Cookie;
           set beresp.ttl = 3600s;
        }
      }

}

(4)设置后端服务器日志中记录真实的客户端地址:

sub vcl_recv {
    if (req.restarts == 0) {
       if (req.http.X-Fowarded-For) {
          set req.http.X-Forwarded-For = req.http.X-Forwarded-For + “,” + client.ip;
    } else {
         set req.http.X-Forwarded-For = client.ip;
       }
    }

}

并在后端服务器中设置日志格式:

vim  /etc/httpd/conf/httpd.conf

  将格式修改为:LogFormat  “%{X-Forwarded-For}i  %l  %u  %t  ”%r“ %>s %b  ” %{Referer}i” ”%{User-Agent}i”” combined

测试:

未分类

(5)访问控制

缓存对象的修剪:purge, ban

未分类

测试:缓存后,用curl查看网页信息

未分类

裁剪,将缓存删除:curl -X PURGE http://172.16.252.187/index.html

未分类

Banning 在交互式模式 用于临时按需要清理缓存

示例:

未分类

在配置文件中,使用ban()函数,相当于purge的用法;示例:

if (req.method == “BAN”) {
      ban(“req.http.host == ” + req.http.host + ” && req.url == ” + req.url);
      return(synth(200, “Ban added”));
}

清空一个域的缓存:

ban req.url == / && req.http.host ~ “ilinux.io”(慎用)

(6)负载均衡,Director:

使用前需要导入:import directors

示例:

未分类

未分类

动静分离配置示例:

         import directors

        …..
        backend imgsrv1 {
                .host = “192.168.251.11”;
                .port = “80”;
        }
        backend imgsrv2 {
                .host = “192.168.251.12”;
                .port = “80”;
        }
        backend appsrv1 {
                .host = “192.168.251.13”;
                .port = “80”;
        }
        backend appsrv2 {
                .host = “192.168.251.14”;
                .port = “80”;
        }
    sub vcl_init {
                new imgsrvs = directors.random();
                imgsrvs.add_backend(imgsrv1,10);
                imgsrvs.add_backend(imgsrv2,20);
                new staticsrvs = directors.round_robin();
                appsrvs.add_backend(appsrv1);
                appsrvs.add_backend(appsrv2);
                new appsrvs = directors.hash();
                appsrvs.add_backend(appsrv1,1);
                appsrvs.add_backend(appsrv2,1);
        }
     sub vcl_recv {
                  if (req.url ~ “(?i).(css|js)$” {
                        set req.backend_hint = staticsrvs.backend();
                }
                if (req.url ~ “(?i).(jpg|jpeg|png|gif)$” {
                       set req.backend_hint = imgsrvs.backend();
                } else {
                        set req.backend_hint = appsrvs.backend(req.http.cookie);
                }
      } 

(7)基于cookie的session sticky:

sub vcl_init {
       new h = directors.hash();
       h.add_backend(one, 1); // backend ‘one’ with weight ‘1’
       h.add_backend(two, 1); // backend ‘two’ with weight ‘1’
}
sub vcl_recv {
       set req.backend_hint = h.backend(req.http.cookie);
} 

(8)健康状态检测:

.probe:定义健康状态检测方法;
.url:检测时要请求的URL,默认为”/”;
.request:发出的具体请求;
    .request =
          “GET /.healthtest.html HTTP/1.1”
          “Host: www.magedu.com”
          “Connection: close”
    .window:基于最近的多少次检查来判断其健康状态;
    .threshold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
    .interval:检测频度;
    .timeout:超时时长;
    .expected_response:期望的响应码,默认为200;

配置示例:

未分类

显示健康状态信息,在交互式界面中:

未分类

4、性能调整:vim /etc/varnish/varnish.params

根据对网页的测试来适当调整数值

未分类

5、varnish日志

1>、varnishstat – Varnish Cache statistics 各种计数器
         -1 批次显示,只显示1次
         -1 -f FILED_NAME
         -l:可用于-f选项指定的字段名称列表;
# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss
# varnishstat -l -f MAIN -f MEMPOOL
2>、varnishtop – Varnish log entry ranking 将日志文件中相关数据逆序排序
              -1 Instead of a continously updated display, print the statistics once and exit.
              -i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;筛选
              -I <[taglist:]regex>
              -x taglist:排除列表
              -X <[taglist:]regex>
varnishtop -i RespStatus 查看响应码
3>、varnishlog – Display Varnish logs 查看实时日志
4>、 varnishncsa – Display Varnish logs in Apache / NCSA combined log format 标准日志格式 

通过Tcpdump抓包 Wireshark分析 找出Wget文件下载失败的原因

在实际工作的过程中,服务程序每日开盘前需要依赖一下静态的文件进行初始化操作,类似版块文件、财务文件、除权文件等文件。由于下载工作比较简单,我们使用linux系统自带的wget,通过shell脚本的方式进行下载,脚本编写完成在测试过程中发现,随着下载频率的增加出现下载不成功的次数会增加,下载到的内容类似:

未分类

从上面的信息可以看到,等到的信息中有类似hs_cc_cookie,初步得出两个怀疑方向:

  • 难道是异常使用cookie导致请求直接返回?
  • 或者是请求被认为是CC攻击,安全设备直接返回了上面的上面的HTML内容??

基于上面的怀疑我们开始问题的排查。

问题排查

1、对wget的请求增加参数

在请求中增加 -S参数,打印详细的响应头,正常下载:

未分类

错误下载:

未分类

然后对请求 增加–no-cookies 参数 ,不使用 cookies ,增加参数后结果一样,多次下载继续出现问题,关于cookies可能性排除,难道真的是安全设备的问题?涉及到跨部门协调,需要拿出证据,那么只能出最后的绝招–网络抓包 ,结果绝对公平公正,童叟无欺。

抓包分析

说到抓包,不得不说说TCP的建立连接的“三次握手”和断开连接的“四次挥手”。
如果觉得有必要回顾一下的同学可以先看看“附录一”,里面会有详细的接收。了然于胸的同学我们继续问题排查。
通过TCPDUMP (LINUX 网络抓包工具)抓取正常下载和异常下载的网络包进行对比分析。

正常下载:

未分类

下载异常:

未分类

下面我们对下载异常的网络包进行分析:

  • 665号包说明服务器认为自己已经完成了服务请求,但客户端却没有主动关闭连接,于是在 20s 后只好主动将连接关闭。665号包显示 “TCP Previous segment not captured” 并且包中 “Seq=640” 而上一个 “Seq=1”我们确实有包没有抓到。

  • 666号包客户端在收到 “Seq=640” 后认为自己收到了一个乱序包,因此试图通过 “TCP Dup ACK 663#1” 和 “Ack=1” 试图让服务器重传缺失的 639 字节。

  • 667号包 出现 “TCP Out-Of-Order” ,产生该问题的原因一般:Packet 可能 Lost,所以重新传送造成。或存在Load Balance 之类的架构,晚送的封包却比早送的到达。

  • 671 号包开始说明客户端由于某种原因还进行了多次针对 “FIN” 的==“TCP Spurious Retransmission”== 。

TCP Previous segment not captured的问题一般有以下几种情况,我们来一一排查。
服务器CPU或网络压力导致上述问题(服务器没有压力)

未分类

  • 杀毒软件、恶意软件监测程序等导致问题(无此问题)。

  • 交换机、路由器和防火墙等网络层问题。

排查到这里,基本可以判断问题是由于网络层相关问题导致,接下来我们从以下两个方向进行问题排查。

1、查看防火墙出口带宽,整个出口我有200M 现在看看只有50M的峰值,和出口带宽无关

未分类

2、查看防火墙关于CC攻击的配置发现开启了IPS防御以及防病毒配置,对于单IP的访问频次过高时,认为是攻击行为会产生丢弃操作,当出现错误请求时有如下报错信息:

未分类

3、调整防火墙配置关闭CC防护,问题解决:

未分类

通过以上的排查我们得出结论:wget在频繁被执行时触发了防火墙的CC攻击防护机制,导致请求被截断从而出现了文章开头的问题。

解决方案:

  • 针对wget下载脚本:
    在增加 中wget 时增加–limit-rate=2048k (限制下载速度为2M)参数,限制下载速度,并增长两次下载过程中的sleep 时间间隔。

  • 针对防火墙:
    适当调高防火墙CC防护的rps值,避免正常请求被防火墙作为CC攻击屏蔽。