一、HAProxy全透明代理


    全透明代理 : 可以用 客户端IP地址或者任何其他地址来连接后端服务器。 这个特性仅在Linux 2.4/2.6内核打了cttproxy 补丁后才可以使用. 这个特性也使得为某特殊服务器处理部分流量同时又不修改服务器的地址成为可能。

   

1.检查系统内核是否已支持Tproxy:

[root@www ~]# grep TPROXY /boot/config-`uname -r`

              CONFIG_NETFILTER_TPROXY=m

              CONFIG_NETFILTER_XT_TARGET_TPROXY=m

看到上述信息,说明内核支持tproxy2.6.32以后的内核,都支持这个功能,无需在打补丁。

要点是,在编译HAProxy时加上 USE_LINUX_TPROXY=1,这是开启全透明代理的参数。

 

2、设置iptables和路由

    安装HAproxy服务的机器,防火墙一定要打开,让所有进入网桥设备的mangle表的包都打上标记,然后新增一条路由规则将这些打了标记的数据包发送至本地回环接口进行处理。

[root@www ~]# ip rule add fwmark 1 lookup 100

[root@www ~]# ip route add local 0.0.0.0/0 dev lo table 100

[root@www ~]# iptables -t mangle -N DIVERT

[root@www ~]# iptables -t mangle -A DIVERT -j MARK --set-mark 1

[root@www ~]# iptables -t mangle -A DIVERT -j ACCEPT

[root@www ~]# iptables -t mangle -A PREROUTING -p tcp -m socket -jDIVERT

 

配置内核参数支持IP转发和对源地址进行检查:

echo 1 > /proc/sys/net/ipv4/conf/all/forwarding

echo 1 > /proc/sys/net/ipv4/conf/all/send_redirects

echo 1 > /proc/sys/net/ipv4/conf/eth0/send_redirects

 

防火墙保存好后,配置文件应该如下:

*mangle

:PREROUTING ACCEPT [0:0]

:INPUT ACCEPT [80:4800]

:FORWARD ACCEPT [0:0]

:OUTPUT ACCEPT [160:8960]

:POSTROUTING ACCEPT [160:8960]

:DIVERT - [0:0]

-A PREROUTING -p tcp -m socket -j DIVERT

-A DIVERT -j MARK --set-xmark 0x1/0xffffffff

-A DIVERT -j ACCEPT

COMMIT

 

3、最重要的一点是修改HAProxy的配置文件,每个 backend server都要加上下边的设置,才能使用全透名模式。

    source 0.0.0.0 usesrc clientip #重点,TPROXY需要加上这行

使用这个功能,要把配置文件中的运行用户和去掉,需要root身份运行才行,然后把后端服务的网管,改成HAproxyip,到此为此基于TProxyHaproxy全透明代理完成了。

    有篇文章说数据再返回客户端的时候,会有问题,还要在改写内核参数,我测试没有发现有此问题,有过,遇到问题,请参考以下文章:

http://www.360doc.com/content/13/0821/17/13047933_308812287.shtml

 

二、Unix套接字命令Unix Socket commands


    socat是一个多功能的网络工具,名字来由是“Socket CAT”,可以看作是netcat的N倍加强版,socat的官方网站:http://www.dest-unreach.org/socat/ 。 

    socat是一个两个独立数据通道之间的双向数据传输的继电器。这些数据通道包含文件、管道、设备(终端或调制解调器等)、插座UnixIP4IP6 - rawUDPTCP)、SSLSOCKS4客户端或代理CONNECT。 

socat支持广播和多播、抽象Unix socketsLinux tun/tapGNU readlinePTY。它提供了分叉、记录和进程间通信的不同模式。多个选项可用于调整socat和其渠道,Socat可以作为TCP中继(一次性或守护进程),作为一个守护进程基于socksifier,作为一个shell Unix套接字接口,作为IP6的继电器,或面向TCP的程序重定向到一个串行线。 

socat的主要特点就是在两个数据流之间建立通道;且支持众多协议和链接方式:ip, tcp, udp, ipv6, pipe,exec,system,open,proxy,openssl,socket等。

    使用socat可以查看和设置HAProxy状态,首先得让HAProxy产生出一个sock出来(hatop socat都是基于这个的,没这个什么都做不了)。

 

1、设置配置文件开启unix socket

global 下面 加一行:

stats socket /usr/local/haproxy/stats #路径和名字随意

然后重启服务就可以了。

 

2、安装socat

从官网下在socat最新版,有人说版本太高安装不上,我没有遇到问题。

[root@www~]# wget http://www.dest-unreach.org/socat/download/socat-1.7.2.4.tar.gz

[root@www~]# tar xf socat-1.7.2.4.tar.gz

[root@www~]# cd socat-1.7.2.4

[root@www~]# ./configure 

[root@www~]# make &&make install

 

3socat使用

echo "help"| socat stdio /usr/local/haproxy/stats    #会有帮助提示

HAProxy高级应用(二)_Session 

echo "show info"| socat stdio /usr/local/haproxy/stats      #资源使用信息

HAProxy高级应用(二)_Session_02

 

echo "show stat"| socat stdio /usr/local/haproxy/stats      #状态信息

HAProxy高级应用(二)_Session_03

     熟悉使用方法后,完全可以使用socat,编写脚本,将HAProxy加到监控里边,实时运行监控状态情况。

HAProxy高级应用(二)_Session_04

HAProxy高级应用(二)_全透明代理_05

    以上仅是获取HAProxy信息,如果想通过socat进行设置HAProxy,权限还是不够的,需要修改配置文件,设置操作权限,修改HAProxy配置文件如下:

    stats socket/usr/local/haproxy/stats level admin          #将等级设置为管理

重启服务,然后就可以操作了。

例如禁用启用成员:

[root@www~]#echo "disable server web_cluters/iask51"|socat stdio/usr/local/haproxy/stats

HAProxy高级应用(二)_全透明代理_06

[root@www ~]# echo "enable serverweb_cluters/iask51"|socat stdio /usr/local/haproxy/stats

HAProxy高级应用(二)_Tproxy_07

[root@www ~]# echo "disable frontend http_80_in"|socat stdio /usr/local/haproxy/stats

HAProxy高级应用(二)_全透明代理_08

[root@www ~]# echo "enable frontend http_80_in"|socat stdio /usr/local/haproxy/stats

HAProxy高级应用(二)_Session_09

    disableenable支持“agent”、frontend”、“health”和server”,命令要比图形界面强大的多,好多参数设定,都可以使用socat来操作。记住一个格式“命令  backend/server”,其它的命令用法自己研究吧。


三、HAProxy负载均衡保持客户端和服务器Session亲缘性的三种方式

 

1、用户IP 识别

    haroxy 将用户IP经过hash计算后 指定到固定的真实服务器上(类似于nginx IP hash 指令),这种方式不用多少,大家都很熟悉,也很常用,就算清空了cookie,同一ip的请求也不会被分发到别的机器上。

配置指令:        balance  source

 

2cookie 识别

    HAProxy WEB服务端发送给客户端的cookie中插入(或添加前缀)haproxy定义的后端的服务器COOKIE ID

    编写一个可插入cookiephp测试页,来验证实验。代码如下:

<html>

    <head>

        <title>PHP测试</title>

    </head>

    <body>

        <?phpecho '<p>Hello World </p>'; ?>

        <?php  echo "访问的服务器地址是:"."<fontcolor=red>".$_SERVER['SERVER_ADDR']."</font>"."<br>";

        echo"访问的服务器域名是:"."<fontcolor=red>".$_SERVER['SERVER_NAME']."</font>"."<br>";

        ?>

    </body>

</html>

 

    配置指令例举  cookieSESSION_COOKIE insert indirect nocache

    SESSION_COOKIE这个名字可以随便起,用firebug可以观察到用户的请求头的cookie 有类似"Cookie jsessionid=0bc588656ca05ecf7588c65f9be214f5; SESSION_COOKIE=app1" SESSION_COOKIE=ask50就是haproxy添加的内容。

    这样haproxy就会按cookie id值分配到对应的服务器上,只要客户端不清除cookie,轮询功能也就失去了作用,和ip hash功能差不多了,当客户端清除cookie后,请求服务器的时候,就会被分发到别的机器上了。

 HAProxy高级应用(二)_全透明代理_10

 

Ctrl+F5刷新后,页面没有变化,cookie id没有变换,访问的是同一台服务器

HAProxy高级应用(二)_Tproxy_11

 

清空浏览器cookie,再次访问,发现页面有变化,访问的是另一台服务器

HAProxy高级应用(二)_Session_12

 

3session 识别

         HAProxy 将后端服务器产生的session和后端服务器标识存在haproxy中的一张表里。客户端请求时先查询这张表。

测试程序代码如下:

<?php

         session_start();

         $_SESSION['time']=date("Y-m-d H:s",time());

         echo "本次访问时间: "."<fontcolor=red>".$_SESSION['time']."</font>"."<br>";

         echo "访问的服务器地址是: "."<fontcolor=red>".$_SERVER['SERVER_ADDR']."</font>"."<br>";

         echo "访问的服务器域名是: "."<fontcolor=red>".$_SERVER['SERVER_NAME']."</font>"."<br>";

         echo"SESSIONNAME: "."<fontcolor=red>".session_name()."</font>"."<br>";

         echo "SESSIONID: "."<fontcolor=red>".session_id()."</font>"."<br>";

?>

         配置指令例举 appsession JSESSIONID len 64 timeout 5hrequest-learn,注意JSESSIONID这个值替换成你的php.ini session.name的值。

 

cookie识别模式差不多

HAProxy高级应用(二)_Session_13

 

Ctrl+F5刷新后,页面没有变化,session id没有变换,访问的是同一台服务器

HAProxy高级应用(二)_Tproxy_14

 

清空浏览器cookie,再次访问,发现页面有变化,访问的是另一台服务器

HAProxy高级应用(二)_Tproxy_15