RPM打包时出现libtool: Version mismatch error问题解决方法

libtool: Version mismatch error.  This is libtool 2.2.6b Debian-2.2.6b-2ubuntu1,
but the
libtool: definition of this LT_INIT comes from an older release.
libtool: You should recreate aclocal.m4 with macros from libtool 2.2.6b
Debian-2.2.6b-2ubuntu1
libtool: and run autoconf again.

这个是执行rpmbuild中的报错信息,解决方案很简单,删除包里的aclocal.m4,然后执行 aclocal 和 autoconf

rm aclocal.m4 & aclocal & autoconf

最后再重新rpmbuild -bb一下就可以了

rpmbuild -bb *.spec
2012/05/18 15:37

LVS网卡软中断配置

这是之前做LVS的网卡软中断配置时整理的一个文档,网上的资料不是很全,将配置方法share给大家。

为什么要配置网卡软中断,主要是因为在网络非常 heavy 的情况下,对于文件服务器、高流量 Web 服务器这样的应用来说,把不同的网卡 IRQ 均衡绑定到不同的 CPU 上将会减轻某个 CPU 的负担,提高多个 CPU 整体处理中断的能力。合理的根据自己的生产环境和应用的特点来平衡 IRQ 中断有助于提高系统的整体吞吐能力和性能。
先看下未升级之前的效果:可以看到网卡软中断被分配到了两个指定的CPU核心上:
lvs1

经过升级内核调整参数后的效果:

lvs2

软中断被均匀的分配到8个核心上,下面来说下具体过程
首先,将内核升级到2.6.32以上,升级过程略去:

为什么要将2.6.18内核升级到2.6.32?
这个主要是因为2.6.18还丌支持RPS这个特性
那什么是rps呢?具体可以参看:
http://lwn.net/Articles/328339/
http://lwn.net/Articles/378617/

为什么要将2.6.18内核升级到2.6.32?
这个主要是因为2.6.18不支持RPS这个特性
那什么是rps呢?具体可以参看:
http://lwn.net/Articles/328339/
http://lwn.net/Articles/378617/ 

第二步:
如果你的服务器网卡和我一样是Broadcom的,那么你就得做这一步,不是请跳到第三步

lvs3

在/etc/modprobe.conf加上下面这行: options bnx2 disable_msi=1
改完这个重新加载下网卡模块modprobe -r bnx2;modprobe bnx2或者重新启动服务器。

为什么要加这个?
这个主要是因为broadcom网卡开启msi后,会造成后面的修改smp_affinity丌生效,intel的网卡没这个问题。
msi是什么?下面的链接有解析:
http://lwn.net/Articles/44139/

第三步:
停用irqbalance
/etc/init.d/irqbalance stop
这个是一个自动调整中断的工具,有兴趣的可以看下irqbalance的官方网站:
http://irqbalance.org/ 

第四步:

设置eth0、eth1对应中断号的 smp_affinity 为 “ff”
先看一下网卡的中断号: 

lvs4

从图中可以看到网卡eth1的中断号为16,eth0的中断号为18
将/proc/irq/中断号/smp_affinity修改为ff,修改完成后就可以开启lvs了,现在中断应该均分到各个核心上了。

smp_affinity这个参数是怎么得来的? 可参考下面链接:
http://www.cs.uwaterloo.ca/~brecht/servers/apic/SMP-affinity.txt

未完待续...

Python colored output

color

 

[root@localhost ~]# cat color.py 
print '\033[1;30mGray like Ghost\033[1;m'
print '\033[1;31mRed like Radish\033[1;m'
print '\033[1;32mGreen like Grass\033[1;m'
print '\033[1;33mYellow like Yolk\033[1;m'
print '\033[1;34mBlue like Blood\033[1;m'
print '\033[1;35mMagenta like Mimosa\033[1;m'
print '\033[1;36mCyan like Caribbean\033[1;m'
print '\033[1;37mWhite like Whipped Cream\033[1;m'
print '\033[1;38mCrimson like Chianti\033[1;m'
print '\033[1;41mHighlighted Red like Radish\033[1;m'
print '\033[1;42mHighlighted Green like Grass\033[1;m'
print '\033[1;43mHighlighted Brown like Bear\033[1;m'
print '\033[1;44mHighlighted Blue like Blood\033[1;m'
print '\033[1;45mHighlighted Magenta like Mimosa\033[1;m'
print '\033[1;46mHighlighted Cyan like Caribbean\033[1;m'
print '\033[1;47mHighlighted Gray like Ghost\033[1;m'
print '\033[1;48mHighlighted Crimson like Chianti\033[1;m'

 

2011/12/14 14:20
Tags: color, python.

Python : 什么是*args和**kwargs?

先来看个例子:

def foo(*args, **kwargs):
print 'args = ', args
print 'kwargs = ', kwargs
print '---------------------------------------'
if __name__ == '__main__':
foo(1,2,3,4)
foo(a=1,b=2,c=3)
foo(1,2,3,4, a=1,b=2,c=3)
foo('a', 1, None, a=1, b='2', c=3)
输出结果如下:

args = (1, 2, 3, 4)
kwargs = {}
---------------------------------------
args = ()
kwargs = {'a': 1, 'c': 3, 'b': 2}
---------------------------------------
args = (1, 2, 3, 4)
kwargs = {'a': 1, 'c': 3, 'b': 2}
---------------------------------------
args = ('a', 1, None)
kwargs = {'a': 1, 'c': 3, 'b': '2'}
---------------------------------------

可以看到,这两个是python中的可变参数。*args表示任何多个无名参数,它是一个tuple;**kwargs表示关键字参数,它是一个dict。并且同时使用*args和**kwargs时,必须*args参数列要在**kwargs前,像foo(a=1, b='2', c=3, a', 1, None, )这样调用的话,会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。

呵呵,知道*args和**kwargs是什么了吧。还有一个很漂亮的用法,就是创建字典:

def kw_dict(**kwargs):
return kwargs
print kw_dict(a=1,b=2,c=3) == {'a':1, 'b':2, 'c':3}
其实python中就带有dict类,使用dict(a=1,b=2,c=3)即可创建一个字典了。

另:连接两个字典的方法:

第一种:

>>> a={'a':'a','b':'b'}
>>> m=dict(c='c',**a)
>>> m
{'a': 'a', 'c': 'c', 'b': 'b'}
>>>

第二种:

>>> a={'a':'a','b':'b'}
>>> m={'c':'c'}
>>> m.update(a)
>>> m
{'a': 'a', 'c': 'c', 'b': 'b'}
>>>

2011/11/27 21:06
Tags: dict, python.

LVS的三种模式区别详解

1. DR模式:(Direct Routing)直接路由模式

DR模式的网络拓扑:

VS-DRouting

1) 工作过程: 当一个client发送一个WEB请求到VIP,LVS服务器根据VIP选择对应的real-server的Pool,根据算法,在Pool中选择一台Real-server,LVS在hash表中记录该次连接,然后将client的请求包发给选择的Real-server,最后选择的Real-server把应答包直接传给client;当client继续发包过来时,LVS根据更才记录的hash表的信息,将属于此次连接的请求直接发到刚才选择的Real-server上;当连接中止或者超时,hash表中的记录将被删除。

2) DR模式的几个细节:
1> LVS和Real-server必须在相同的网段:(相同的广播域内)
DR模式在转发client的包时,只修改了包目的MAC地址为选定的Real-server的mac地址,所以如果LVS和Real-server在不通的广播域内,那么Real-server就没办法接收到转发的包。下面是mac地址的修改过程:

VS-DR-flow

2> LVS不需要开启路由转发:
LVS的DR模式不需要开启路由转发功能,就可以正常的工作,出于安全考虑,如果不需要转发功能,最好关闭。

3> ARP问题:
通常,DR模式需要在Real-server上配置VIP,配置的方式为:

/sbin/ifconfig lo:0 inet VIP netmask 255.255.255.255

i) 原因在于,当LVS把client的包转发给Real-server时,因为包的目的IP地址是VIP,那么如果Real-server收到这个包后,发现包的目的IP不是自己的系统IP,那么就会认为这个包不是发给自己的,就会丢弃这个包,所以需要将这个IP地址绑到网卡上;当发送应答包给client时,Real-server就会把包的源和目的地址调换,直接回复给client。

ii) 关于ARP广播:
* 上面绑定VIP的掩码是”255.255.255.255″,说明广播地址是其本身,那么他就不会将ARP发送到实际的自己该属于的广播域了,这样防止与LVS上VIP冲突,而导致IP冲突。
* 另外在Linux的Real-server上,需要设置ARP的sysctl选项:(下面是举例说明设置项的)

假设服务器上ip地址如下所示:

System Interface MAC Address IP Address
HN eth0 00:0c:29:b3:a2:54 192.168.18.10
HN eth3 00:0c:29:b3:a2:68 192.168.18.11
HN eth4 00:0c:29:b3:a2:5e 192.168.18.12
client eth0 00:0c:29:d2:c7:aa 192.168.18.129

当我从192.168.18.129 ping 192.168.18.10时,tcpdump抓包发现:

00:0c:29:d2:c7:aa > ff:ff:ff:ff:ff:ff, ARP, length 60: arp who-has 192.168.18.10 tell 192.168.18.129
00:0c:29:b3:a2:5e > 00:0c:29:d2:c7:aa, ARP, length 60: arp reply 192.168.18.10 is-at 00:0c:29:b3:a2:5e
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, ARP, length 60: arp reply 192.168.18.10 is-at 00:0c:29:b3:a2:54
00:0c:29:b3:a2:68 > 00:0c:29:d2:c7:aa, ARP, length 60: arp reply 192.168.18.10 is-at 00:0c:29:b3:a2:68
00:0c:29:d2:c7:aa > 00:0c:29:b3:a2:5e, IPv4, length 98: 192.168.18.129 > 192.168.18.10: ICMP echo request, id 32313, seq 1, length 64
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, IPv4, length 98: 192.168.18.10 > 192.168.18.129: ICMP echo reply, id 32313, seq 1, length 64
00:0c:29:d2:c7:aa > 00:0c:29:b3:a2:5e, IPv4, length 98: 192.168.18.129 > 192.168.18.10: ICMP echo request, id 32313, seq 2, length 64
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, IPv4, length 98: 192.168.18.10 > 192.168.18.129: ICMP echo reply, id 32313, seq 2, length 64
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, ARP, length 60: arp who-has 192.168.18.129 tell 192.168.18.10
00:0c:29:d2:c7:aa > 00:0c:29:b3:a2:54, ARP, length 60: arp reply 192.168.18.129 is-at 00:0c:29:d2:c7:aa

三个端口都发送了arp的reply包,但是192.168.18.129使用的第一个回应的eth4的mac地址作为ping请求的端口,由于192.168.18.10是icmp包中的目的地址,那么ping的应答包,会从eth0端口发出。

如果Real-server有个多个网卡,每个网卡在不同的网段,那么可以过滤掉非本网卡ARP请求的回应;但是如果多个网卡的ip在一个网段,那么就不行了。

sysctl -w net.ipv4.conf.all.arp_filter=1

对于多个接口在相同网段可以设置下面的来防止:

sysctl -w net.ipv4.conf.all.arp_ignore=1
sysctl -w net.ipv4.conf.all.arp_announce=2

还是从192.168.18.129 ping 192.168.18.10时,tcpdump抓包发现:

00:0c:29:d2:c7:aa > ff:ff:ff:ff:ff:ff, ARP, length 60: arp who-has 192.168.18.10 tell 192.168.18.129
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, ARP, length 60: arp reply 192.168.18.10 is-at 00:0c:29:b3:a2:54
00:0c:29:d2:c7:aa > 00:0c:29:b3:a2:54, IPv4, length 98: 192.168.18.129 > 192.168.18.10: ICMP echo request, id 32066, seq 1, length 64
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, IPv4, length 98: 192.168.18.10 > 192.168.18.129: ICMP echo reply, id 32066, seq 1, length 64
00:0c:29:d2:c7:aa > 00:0c:29:b3:a2:54, IPv4, length 98: 192.168.18.129 > 192.168.18.10: ICMP echo request, id 32066, seq 2, length 64
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, IPv4, length 98: 192.168.18.10 > 192.168.18.129: ICMP echo reply, id 32066, seq 2, length 64
00:0c:29:b3:a2:54 > 00:0c:29:d2:c7:aa, ARP, length 60: arp who-has 192.168.18.129 tell 192.168.18.10
00:0c:29:d2:c7:aa > 00:0c:29:b3:a2:54, ARP, length 60: arp reply 192.168.18.129 is-at 00:0c:29:d2:c7:aa

看到了么,现在只有eth0会回应arp请求了。

arp报文格式:

arp

请求报文:MAC地址字段是空的。
应答报文:所有字段都又内容。

The arp_announce/arp_ignore reference:

arp_announce – INTEGER
Define different restriction levels for announcing the local
source IP address from IP packets in ARP requests sent on
interface:
0 – (default) Use any local address, configured on any interface
1 – Try to avoid local addresses that are not in the target’s
subnet for this interface. This mode is useful when target
hosts reachable via this interface require the source IP
address in ARP requests to be part of their logical network
configured on the receiving interface. When we generate the
request we will check all our subnets that include the
target IP and will preserve the source address if it is from
such subnet. If there is no such subnet we select source
address according to the rules for level 2.
2 – Always use the best local address for this target.
In this mode we ignore the source address in the IP packet
and try to select local address that we prefer for talks with
the target host. Such local address is selected by looking
for primary IP addresses on all our subnets on the outgoing
interface that include the target IP address. If no suitable
local address is found we select the first local address
we have on the outgoing interface or on all other interfaces,
with the hope we will receive reply for our request and
even sometimes no matter the source IP address we announce.

The max value from conf/{all,interface}/arp_announce is used.

Increasing the restriction level gives more chance for
receiving answer from the resolved target while decreasing
the level announces more valid sender’s information.

arp_announce用来限制,是否使用发送的端口的ip地址来设置ARP的源地址:
* “0″代表是用ip包的源地址来设置ARP请求的源地址。
* “1″代表不使用ip包的源地址来设置ARP请求的源地址,如果ip包的源地址是和该端口的IP地址相同的子网,那么用ip包的源地址,来设置ARP请求的源地址,否则使用”2″的设置。
* “2″代表不使用ip包的源地址来设置ARP请求的源地址,而由系统来选择最好的接口来发送。

当内网的机器要发送一个到外部的ip包,那么它就会请求路由器的Mac地址,发送一个arp请求,这个arp请求里面包括了自己的ip地址和Mac地址,而linux默认是使用ip的源ip地址作为arp里面的源ip地址,而不是使用发送设备上面的 ,这样在lvs这样的架构下,所有发送包都是同一个VIP地址,那么arp请求就会包括VIP地址和设备 Mac,而路由器收到这个arp请求就会更新自己的arp缓存,这样就会造成ip欺骗了,VIP被抢夺,所以就会有问题。

现在假设一个场景来解释arp_announce:
Real-server的ip地址: 202.106.1.100(public local address),172.16.1.100(private local address),202.106.1.254(VIP)

如果发送到client的ip包产生的arp请求的源地址是202.106.1.254(VIP),那么LVS上的VIP就会被冲掉,因为交换机上现在的arp对应关系是Real-server上的VIP对应自己的一个MAC,那么LVS上的VIP就失效了。

arp_ignore – INTEGER
Define different modes for sending replies in response to
received ARP requests that resolve local target IP addresses:
0 – (default): reply for any local target IP address, configured
on any interface
1 – reply only if the target IP address is local address
configured on the incoming interface
2 – reply only if the target IP address is local address
configured on the incoming interface and both with the
sender’s IP address are part from same subnet on this interface
3 – do not reply for local addresses configured with scope host,
only resolutions for global and link addresses are replied
4-7 – reserved
8 – do not reply for all local addresses

The max value from conf/{all,interface}/arp_ignore is used
when ARP request is received on the {interface}
“0″,代表对于arp请求,任何配置在本地的目的ip地址都会回应,不管该arp请求的目的地址是不是接口的ip;如果有多个网卡,并且网卡的ip都是一个子网,那么从一个端口进来的arp请求,别的端口也会发送回应。

“1″,代表如果arp请求的目的地址,不是该arp请求包进入的接口的ip地址,那么不回应。
“2″,要求的更苛刻,除了”1″的条件外,还必须要求arp发送者的ip地址和arp请求进入的接口的ip地址是一个网段的。
(后面略)

2.IP Tunneling模式:
IP Tunneliing的拓扑图

VS-IPTunneling

1) 工作过程:
1> client 发送request包到LVS服务器的VIP上。

2> VIP按照算法选择后端的一个Real-server,并将记录一条消息到hash表中,然后将client的request包封装到一个新的IP包里,新IP包的目的IP是Real-server的IP,然后转发给Real-server。

3> Real-server收到包后,解封装,取出client的request包,发现他的目的地址是VIP,而Real-server发现在自己的lo:0口上有这个IP地址,于是处理client的请求,然后将relpy这个request包直接发给client。

4> 该client的后面的request包,LVS直接按照hash表中的记录直接转发给Real-server,当传输完毕或者连接超时,那么将删除hash表中的记录。

2) 几个细节问题:
1> IP封包的过程:(如图)

VS-TUN-flow

2> LVS和Real-server不需要在一个网段:
由于通过IP Tunneling 封装后,封装后的IP包的目的地址为Real-server的IP地址,那么只要Real-server的地址能路由可达,Real-server在什么网络里都可以,这样可以减少对于公网IP地址的消耗,但是因为要处理IP Tunneling封装和解封装的开销,那么效率不如DR模式。

3> Real-server的系统设置:(由于需要Real-server支持IP Tunneling,所以设置与DR模式不太一样,LVS不需要设置tunl设备,LVS本身可以进行封装)
i) 需要配置VIP在tunl设备上:(VIP:172.16.1.254)

shell> ifconfig tunl0 172.16.1.254 netmask 255.255.255.255
shell> ifconfig tunl0
tunl0 Link encap:IPIP Tunnel HWaddr
inet addr:172.16.1.254 Mask:255.255.255.255
UP RUNNING NOARP MTU:1480 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

当添加tunl0设备时,自动载入需要的模块:

shell> lsmod |grep ipip
ipip 7516 0
tunnel4 2700 1 ipip

其中,ipip依赖于tunnel4,假如现在删除tunnel4的话:

shell> rmmod tunnel4
ERROR: Module tunnel4 is in use by ipip

如果添加tunl0失败,那么可能是内核没有开启tunneling功能,默认是以模块形式,加载到内核里的:

tunneling_mod

3) ARP问题:
如果LVS和Real-server不在一个网络内,不需要处理ARP问题,如果在相同网络,那么处理方法和DR模式一样,但是如果一样,我就不知道选择tun模式有什么好理由了,DR似乎效率更高些吧。

4) 内核的包转发:
IP Tunneling模式不需要开启ip_forward功能。

3. NAT模式:
NAT模式的拓扑图

VS-NAT

1) 工作过程:

RunningExample

client:202.100.1.2
VIP:202.103.106.5
Real-server:172.16.0.2 和 172.16.0.3(提供http和ftp服务)

1> client发送request到LVS的VIP上,VIP选择一个Real-server,并记录连接信息到hash表中,然后修改client的request的目的IP地址为Real-server的地址,将请求发给Real-server;

2> Real-server收到request包后,发现目的IP是自己的IP,于是处理请求,然后发送reply给LVS;

3> LVS收到reply包后,修改reply包的的源地址为VIP,发送给client;

4> 从client来的属于本次连接的包,查hash表,然后发给对应的Real-server。

5> 当client发送完毕,此次连接结束或者连接超时,那么LVS自动从hash表中删除此条记录。

下面是地址转换的过程:

Screenshot

2) 几个细节问题:
1> NAT模式的Bugs:(都已经修复,具体的信息看LVS的howto)
i) 在Linux的2.6版本,LVS-NAT不能做防火墙,在只有一个网关的情况下,没有任何问题。
ii) 防火墙不兼容:LVS的架构中,LVS的前端不能设置防火墙,修复的补丁”NFCT” patch。
iii) 源路由问题

2> ICMP重定向问题:
i) 对于路由器来说,只有当如下条件同时满足的时候,才进行重定向:
a) 数据包的入接口和路由后的指定的出接口是同一个接口。
b) 数据包的源IP地址和该包应走的下一跳IP地址属于同一个网段。
c) 数据报非源路由的(这种情况应该比较少见了,源路由多见于Token Ring)。
d) 系统开启重定向功能。
例如:
两个路由器都开启了IP重定向功能。HostA 的默认网关为1.1.1.1。当HostA要和不在同一网段中的HostB通信的时候,会把数据报递交给默认网关RT1。然而RT1经过查找发现到达3.3.3.3的路径下一跳恰恰是经由自己的E0/1口的RT2接口1.1.1.2。满足上述条件,将会发生重定向。

ii) LVS为什么会产生ICMP重定向问题:
* 在LVS-NAT模式下,如果LVS的各个成员,client,LVS,Real-server在同一个网段(比如:192.168.1.*/24);

* 当Real-server将Reply发送回LVS时,Reply包是 RIP -> CIP的,LVS看到RIP-> CIP实际上根本没必要经过LVS,直接到网关就行了,因为大家在一个网段,所以产生ICMP重定向发送给Real-server;

* Real-server收到ICMP重定向包后,如果Real-server的ICMP重定向开启了,Real-server就会处理ICMP重定向包,直接将Reply包发给网关,这时Reply包头并没有被LVS重写,所以LVS负载出现了问题。

注意:这种情况只会出现在所有的LVS的成员都在一个网段的情况下。

重定向的处理办法(Real-server的配置):
1> 关闭Real-server的重定向,忽略LVS发来的重定向包
2> 删除到网段的路由:

Screenshot1

执行:

realserver:/etc/lvs#route del -net 192.168.1.0 netmask 255.255.255.0 dev eth0

路由已经被删除了:

Screenshot-1

3> LVS-NAT模式支持四层的端口重写:
LVS-DR,LVS-TUN不能修改client发来的请求的目的端口,但是LVS-NAT可以,参考命令:

shell> ipvsadm -a -t VIP:PORT -r RIP:NEWPORT -m -w 1

LVS的三种转发模式就先说到这吧,具体的细节可以参考LVS的HOWTO文档。

2011/11/08 10:36
Tags: dr, load balance, lvs, nat.

《web安全技术沙龙》一些感想

昨天在中科院软件所参加了spark组织的安全技术沙龙的会议,参加这个沙龙,我的第一个收获应该是见着了spark的真人了,真人比人人网上的照片要帅多了。嘿嘿…

下面来说说安全沙龙上的一些内容吧,昨天cnbird讲的安全运维的内容我是非常感兴趣的,主要讲了两个案例,一个是nfs对公网开放,一个squid的acl没配置好,这两个应该都是管理员的疏忽造成的,很容易进行修复,如何去避免这些疏忽呢,我们系统管理员,应该也可以做做相关的工作,比如拿着nmap自己扫扫,看看有没有多余的端口暴露在外网,平时多关注操作系统,服务器软件方面的一些漏洞(0day信息),去年5月份的时候80sec爆出nginx文件类型错误解析漏洞,这个漏洞大致是nginx默认情况下可能导致服务器错误的将任何类型的文件以PHP的方式进行解析,这使得攻击者可能攻陷支持php的nginx服务器。这个漏洞爆出后,有很多反应不及时的管理员的论坛被黑客拿到了webshell,据说当当网的论坛也被黑掉了。

上面说的主要是运维安全,光服务器配置,防火墙配好了,这些还不够,很多的的安全问题是由应用造成的,下面再来说说昨天会上讲的一些应用安全方面的内容,主要讲的关于XSS方面的东西,XSS漏洞很常见,解决起来也非常简单,就是转义,在写网站上,我们应该遵循,用户的一切输入都不可信,都要进行转义,这个问题,其实一些成熟的web开发框架内置了很好的解决方案,比如我比较熟悉的django,它默认会对用户所有的输入内容进行转义,并且一般在使用django开发网站时,在开发过程中我们一般使用ORM来对数据库进行操作,这样可以有效避免sql注入攻击,还有对于目录遍历漏洞,django内置的静态内容视图会对../../这样输入进行转义,更进一步来说django的url配置文件,如果我们没在urlconf中进行相应的配置,那么我们也是没法进行访问。昨天在沙龙上来自新浪的cy07说的很好,根据refer来防范XSS,保证两次refer一致才允许访问,避免用户的cookie被盗。

最后再说说安全制度,体系,流程的问题,大部分的公司一般都是在出了问题之后才开始重视这些问题,非常的被动,不是主动的去做安全,做安全的话,需要自上而下进行推动,因此需要相应的制度,体系,流程,一般我们做技术的对于这些东西都是比较反感,感觉被这些东西束缚住了手脚,可以这样去想一下,如果一个流程能减少安全问题,那么我们就可以少花一点时间再出事以后修修补补。好了,就写这么多吧,有点小的建议,web安全沙龙可以讲讲一些网络安全方面的东西,比如ddos防范之类的内容,希望web安全技术沙龙能越办越火。

2011/10/31 22:48

python的lambda函数介绍

今天在论坛上看到有人问的一个关于如何从一个python的字典中取到value中最大的那个key值,里面用到了lambda函数,今天那就大致介绍下lambda是个什么东东。
python支持创建一种匿名的函数(一种没绑定名字的函数),这种函数叫做lambda,这个和fp(函数编程)里面的lambda的含义并不是完全一致,下面这段代码将展示lambda和普通函数之间的区别

 >>> def f (x): return x**2
 ...
 >>> print f(8)
 64
 >>>
 >>> g = lambda x: x**2
 >>>
 >>> print g(8)
 64

g()是一个 lambda 函数,完成同上面普通函数相同的事情。注意这里的简短的语法:在参数列表周围没有括号,而且忽略了 return 关键字 (隐含存在,因为整个函数只有一行)。而且,该函数没有函数名称,但是可以将它赋值给一个变量进行调用。
使用 lambda 函数时甚至不需要将它赋值给一个变量。这可能不是世上最有用的东西,它只是展示了 lambda 函数只是一个内联函数。

总的来说,lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值。lambda 函数不能包含命令,包含的表达式不能超过一个。不要试图向 lambda 函数中塞入太多的东西;如果你需要更复杂的东西,应该定义一个普通函数,然后想让它多长就多长。
这里只是大致介绍一下,想深入研究的可以看文章后面附的文档,这里回到开头的问题,如果返回一个字典中最大的value值的key,下面为代码:

>>> dict = {'a':1,'b':2,'c':3}
>>> max(dict.iterkeys(),key=lambda k:dict[k])
'c'
>>>

下面来大致解释这段代码,先定义了一个列表,通过使用key参数改变了max比较列表元素的方法,最终达到了取得value值最大的key的目的。
接下来讲一下,python字典的iterkeys,iteritems,itervalues这三个方法,字典对象也提供keys,items,values这三个方法,那前面的三种方法和后面的三种方法有什么不一样呢,我们大致运行一下就可以知道了,前面的三个方法返回迭代器对象,而后三种方法返回的为列表对象,使用前三种方法更高效一些,后三种方法对内存占用比较大,在python 3.0中取消了iterkeys,iteritems,itervalues这三个方法,将keys,items,values这三个方法功能改为原来iter*的功能。
参考文档:
lambda介绍:http://hi.baidu.com/pythonhome/blog/item/cdd68eb0a4de30b2d8335afe.html
Python: Lambda Functions: http://www.secnetix.de/olli/Python/lambda_functions.hawk
Python: Built-in Functions: http://docs.python.org/library/functions.html

2011/10/29 22:48
Tags: lambda, python.

使用NGINX+UWSGI来部署Django

关于UWSGI的介绍不多说了,想了解的可以自己去搜,uwsgi性能还蛮不错,我们之前使用的fastcgi方式来跑django,前端用F5做负载均衡,用户数增加后服务器的load很高,但换uwsgi服务器的load下降不少,废话不多说,进入正题。
编译安装nginx,用的nginx-0.8.54,目前最新的stable版本

#wget http://nginx.org/download/nginx-0.8.54.tar.gz
#tar zxvf  nginx-0.8.54.tar.gz
#./configure --user=nobody
 --group=nobody
--prefix=/usr/local/nginx
--with-http_ssl_module
 --http-log-path=/var/log/nginx/access.log
--with-http_gzip_static_module
#make&&make install

下面来安装uwsgi

#wget http://projects.unbit.it/downloads/uwsgi-0.9.6.5.tar.gz
#tar zvxf uwsgi-0.9.6.5.tar.gz
#cd uwsgi-0.9.6.5
#make -f Makefile.Py26
#cp uwsgi /usr/sbin/uwsgi    #将uwsgi放到PATH下

下面来说说怎么配置:
新建一个uwsgi.xml的文件放到django的目录下

#cat uwsgi.xml
<uwsgi>
<socket>0.0.0.0:8000</socket>
<listen>204800</listen>
<processes>32</processes> #开启32个线程
<max-requests>2048000</max-requests>
<buffer-size>8192</buffer-size>
<module>django_wsgi</module> #你的配置文件
<profiler>true</profiler>
<enable-threads>true</enable-threads>
<limit-as>256</limit-as> #限制内存空间256M
<async>10</async> #使用async模式来运行,这里要注意一下,
如果你的app的是no-async-friendly 那就不要用这个模式 <disable-logging/>
<daemonize>/home/app01/uwsgi.log</daemonize>
</uwsgi>
#cat django_wsgi.py import os import django.core.handlers.wsgi os.environ['DJANGO_SETTINGS_MODULE'] = 'your settings' application = django.core.handlers.wsgi.WSGIHandler()

下面是nginx的配置:

server {
	listen   80;
	server_name jasonwu.me;
	access_log /var/log/jasownu.me/access_log;
	location / {
                root   /home/app01/
		uwsgi_pass 127.0.0.1:8000;
		include        uwsgi_params;
	}
}

启动服务:
#/usr/bin/uwsgi -x /home/app01/uwsgi.xml
#/usr/local/nginx/sbin/nginx
这样部署完成了

下面来说说遇到的一个问题,不知道大家有没有遇到过,
在我们启动uwsgi后在uwsgi的日志中会出现如下的信息:
– unavailable modifier requested: 1 –
– unavailable modifier requested: 1 –
表现的现象就是启动一段时间没法访问app,在查看uwsgi的源代码中我们找到打印这部份日志的段落,正常情况下应该返回的-1,目前还在查找这个出现这个错误的原因。

附:uwsgi的官方wiki
Programming in Python with Medusa and the Async Sockets Library

2011/10/29 22:46