Tag: linux

tcp 内核参数对NAT 用户的影响

非原创,前同事参详出来的,我知道一下原因,但今天遇到了,决定mark 一下。

故障现象:

NAT 用户,也就是使用同一个出口ip 的那些用户,例如,使用办公网络的用户。NAT 用户访问网站时,表现为连接不上,技术一点说,就是建立不了tcp 握手。

很奇怪吧?同一个网络的用户,我可以访问,旁边的同学就不能访问。难道是RPWT 吗?

在网上可以搜到一个很普遍的系统优化方法,修改/etc/sysctl.conf ,添加

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_tw_reuse = 1

sysctl -p 让内核参数生效。

以前大家通常会遇到netstat 看到很多 TIME-WAIT 状态的连接,于是就会添加以上两句,加速回收TIME-WAIT 的资源。

但是这个优化现在已经行不通了。

为了提高TCP的性能,“RFC1323 – TCP Extensions for High Performance”提出了 一个机制(http://tools.ietf.org/html/rfc1323#page-29)来替代TIME- WAIT状 态的功能。linux 实现了它。这个机制通过记录来自每台主机的每个连接的分组时间戳来实现,要求 来自同一主机的同一连接的分组所携带的时间戳要比之前记录 的时间戳新,以便 “防止回绕的序号PAWS机制“ (http://tools.ietf.org/html/rfc1323#page-17) 丢弃接收属于旧连接的延时分组。这依赖于来自每个主机的每个 TCP连接分组所携 带的时间戳要单调递增才能实现。然而经过NAT的连接,其分组携带时间戳每个用户都不同的(甚至有人写了个论文,利用这个分组的时间戳来计算NAT 后端有多少台主机 http://phrack.org/issues.html?issue=63&id=3#article),也就是说同一个ip ,携带的时间戳不会单调递增。服务器端对同一个ip 过来的包的timestamp 做一个验证,导致这些连接分组被认为是属于旧 连接的延时分组而被丢弃。

具体有多少被drop 的包呢??请看 netstat -s 的其中一行

7439 packets rejects in established connections because of timestamp

为了防止这种情况呢,也很简单,修改一下内核参数,把 /proc/sys/net/ipv4/tcp_tw_{reuse,recycle} 的值都置为 0 吧。

为了纪念我连续工作超过24 小时

本周的第一天起床,多美好的一天啊,天清气爽的。9 点起床,10点半来到公司,恶梦才开始!!

服务器连续down 机,极其不稳定,由于各类服务我还没有上手,无奈,大部分情况下是眼睁睁地看着服务器down 的。晚上8 点到机房,12 点才把服务器装好上架。弄服务等东西,一直到了周二晚上的9 点左右,才把任务完成。服务器算是冷静下来了,算是过渡到一个较为稳定的状态了。打车回家,12 点躺下!共计39 小时,中间只是稍微趴了一下,大概就10+ 分钟。

为了纪念我连续工作超过24 小时,整整一天没有睡觉,我写下了这篇blog 。

虽然苦和累,但这段时间学习到的东西,在我旧东家可能得一个月了,因为时间都花费在和不懂技术的人的沟通去了,不错不错,哈哈。列几个遇到的问题和解决方案吧。

1,ubuntu server 的启动

装完以后,竟然开机启动后,载入到USB 的时候,会出现以下错误:

Gave up waiting for root device. Common problems:
-Boot args (cat /proc/cmdline)
-Check rootdelay= (did the system wait long enough?)
-Check root= (did the system wait for the right device?)
-Missing modules (cat /proc/modules; ls /dev)
/dev/disk/by-uuid/34e5c1 … does not exist …

然后就在 (initramfs) 这个提示符下了。

其实在这里,不算开不了机,exit 退出,就ok 了,继续linux 的启动过程,login 画面。

我的猜想嘛,内核没载入?也不是。不认 uuid ?也不是。本来不是大事情,exit 一下就好,但如果没有人在机器身边,那就无法重启了。

原因:initramfs 在载入到USB 驱动的时候,没载入完毕!必须等待其载入完毕,在内核里加一个rootdelay 就好了。

/boot/grub/grub.cfg 里,找到

linux   /vmlinuz-2.6.35-22-server root=UUID=541215f0-c868-40ec-b1d7-c7d083f18b80 ro   quiet

修改为
linux   /vmlinuz-2.6.35-22-server root=UUID=541215f0-c868-40ec-b1d7-c7d083f18b80 ro   quiet rootdelay=60
rootdelay 的时间,随意,30 或 60 应该都ok ,看自己机器的载入快慢吧,10 就太快了,呵呵。

2,ubuntu 的用户家目录加密

安装ubuntu 千万别加这个吧,哈哈。

encrypted home directory , 安装的时候,加上的话,用户的家目录就很安全了。会有以下情况出现。

/home/hello 是我的家目录,我没有登陆的话,如果有另一个用户想访问我的家目录,他会看不见我的家目录的所有被加密的所有文件,空空如也,简直好像被黑了!!

安全吧??但是,如果我有程序跑在我的家目录下呢??好吧,404 了,也爽歪歪了。

暂时没解决这个问题,因为太困了。也不敢贸然把 .Private 这类目录删了,以后在测试环境下弄。

3,DELL 的iDRAC6 远程控制卡

旧东家就是不帮我们弄一个远程控制卡,不搞无人值守机房。

我总算是玩到了这个东西了,不过因为连接的是内网,需要搭建一个vpn ,拨入vpn 以后,通过内网地址访问远程控制卡。

一个web 界面,我只是初玩,没时间细玩,have fun 。

4,DBA 了。

旧东家分工细了一点,有专门的DBA 。于是,我的DBA 技术到了09 年后,就没增长了。很多知识都落后了。

重新拾回来,实操了一下,充实!

5,nosql 了。

mongodb 更细致地看了一下,爽!

还有一些吧,忘了。第一次跨越一天的工作,累,但很爽,哈哈。

kernel 2.6.32 的服务器作为lvs 的rs 无法建立tcp 连接的问题

最近用xen 的虚拟机作为lvs 的rs 组了一下lvs ,发现上线以后,无法与client 建立tcp 连接,开始还以为是xen 的bridge 网络的问题,后来才把问题定位到系统内核。其实之前也出现过类似的问题的,但当时急着上线,没去研究了,这回太忙,连测试环境都搭出来了,也都没空去深究,今天同事帮我测试了一下,倒是完全明白了。

问题描述:

LVS 用dr 的方式组起来以后,访问vip 时,无法与real server 建立tcp 连接。tcpdump 看到只有client 过来的syn 包,rs 并不返回ack 包,根本无法完成tcp 握手。用curl 来模拟访问测试的话,会看到这样的返回 curl: (7) couldn’t connect to host 。

看看我的配置吧。

lvs director :

采用dr 的调度方式,通过内网把请求分配到real server

lvs 的 real server :

内核为 2.6.32-5-amd64 (2.6.32 这个内核很普遍了,debian 6 和 rhel 6 默认都这个了),不响应arp 配置

echo “1” >/proc/sys/net/ipv4/conf/lo/arp_ignore
echo “2” >/proc/sys/net/ipv4/conf/lo/arp_announce
echo “1” >/proc/sys/net/ipv4/conf/all/arp_ignore
echo “2” >/proc/sys/net/ipv4/conf/all/arp_announce

其它基本的配置就不说了,如果就这样子起服务后,就会出现我描述的问题了。

原因在于内核的这个参数 : reverse path filtering,这个是啥,我摘抄一下:

Reverse Path Filtering (RPF) is a technology that is used on InternetProtocol routers to try and prevent source address spoofing, which is often used for DenialOfService attacks. RPF works by checking the source IP of each packet received on an interface against the routing table. If the best route for the source IP address does not use the same interface that the packet was received on the packet is dropped. There are some situations where this feature will obviously not be the desired behaviour and will need to be disabled. In general if you are not multi-homed then enabling RPF on your router will not be a problem.

简单地说,就是如果从eth1 接收到包,就不会从eth0 返回,内核把这个包丢弃。

正好我们的LVS 就是这样的服务模式,lvs director 接收到client 对vip 的访问,经过包的重写通过内网把包分配给rs ,rs 直接使用外网返回这个client 的请求。正好就会被rp_filter 给干掉了。

但是,为什么我们以前并没有出现过类似的问题呢??看看rp_filter 的默认内核配置

net.ipv4.conf.eth1.rp_filter = 1

net.ipv4.conf.eth0.rp_filter = 1

net.ipv4.conf.lo.rp_filter = 0

net.ipv4.conf.default.rp_filter = 1

net.ipv4.conf.all.rp_filter = 0

rp_filter 的值的意义是:

814 rp_filter – INTEGER

815 0 – No source validation.

816 1 – Strict mode as defined in RFC3704 Strict Reverse Path

817 Each incoming packet is tested against the FIB and if the interface

818 is not the best reverse path the packet check will fail.

819 By default failed packets are discarded.

820 2 – Loose mode as defined in RFC3704 Loose Reverse Path

821 Each incoming packet’s source address is also tested against the FIB

822 and if the source address is not reachable via any interface

823 the packet check will fail.

0 就是对进来的包完全不作检查,这样有被dos 攻击的风险。

1 就是严格检查,只要不是这个interface 的包,就不返回。

2 就是不太严格,只要本机配置了这个ip ,还是可以返回的。

对于lvs 来说,用2 也是可以的。

只要把eth1 的 rp_filter 的值置为 0 ,lvs 的服务就能正常了。

从这里可以找到答案:http://www.spinics.net/lists/linux-net/msg17162.html

The first patch changed rp_filter from a boolean to an integer, and the

second patch changed the way the interface-specific value and the “all”

value are combined to produce a functional value from a logical AND to

an arithmetic MAX.

Before patches : functional value = interface AND all

After patches  : functional value = MAX(interface, all)

So now if net.ipv4.conf.all.rp_filter=1, source validation is enabled on

all interfaces as their functional value is at least 1. You may either

set net.ipv4.conf.all.rp_filter to 0 (to disable it) or 2 (to enable

loose mode globally), or set net.ipv4.conf.$interface.rp_filter to 2 (to

enable loose mode on $interface).

I guess that the patch suggested by Dave Miller is related to another

(apparently incomplete) change that occured in 2.6.32 :

在2.6.31 , 对于rp_filter 的最终值,有了不同的计算方法。

之前,是只要设置了all.rp_filter 为0 ,那么就是0 了。

之后,看具体的interface 和 all 的值的最大值来取最终值。

默认是 net.ipv4.conf.eth1.rp_filter = 1 和 net.ipv4.conf.all.rp_filter = 0 ,因此,组lvs 的时候,就会丢弃包了。

问题解决!!下次调一下内核参数吧。

PS:可以通过设置这个内核参数来查看一下log

echo 1 >/proc/sys/net/ipv4/conf/<interfacename>/log_martians

cnnic 证书更新问题

最近为部门内部系统的https 快要过期的证书更新,出现了一系列的问题,很是郁闷!!一个字:恨!!

原来从2010 年 3 月后,由cnnic 签发的证书,有所改变了。2010 年 3 月前,root CA 是 entrust ,中级CA 是cnnic 。3 月后,root 和中级CA ,都是cnnic 了。。。

cnnic 证书本身就没有多少诚信可言了,还做了root CA 。。。

举例说明:

$curl -I https://blog.helosa.org/ 的时候,会有这类报错

curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a “bundle”
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn’t adequate, you can specify an alternate file
using the –cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you’d like to turn off curl’s verification of the certificate, use
the -k (or –insecure) option.

提示是说,加一个-k 的参数,就不会去验证证书了,但我想了解一下原因。它也给了提示,让我们去这个网页http://curl.haxx.se/docs/sslcerts.html 里了解详情。

通读了一次,大概了解了,因为root 和中级CA 都是cnnic ,并且根CA 的证书并不在curl 的信任列表里,curl 认为它是self-signed 证书,不安全,于是就报错了。

解决方案嘛,把cnnic 的root 证书wget 回来,在这里:http://www.cnnic.cn/uploadfiles/cer/2010/3/2/113823.cer

然后curl 时加上这个证书,curl –cacert 113823.cer https://blog.helosa.org/

=====================================================

在这个问题上,我有两个不明白的地方:

1,其实,可以将cnnic 的root 证书加入到信任列表的,信任列表在/etc/ssl/certs/ 里,通过 curl -vv 可以看到

CAfile: none

CApath: /etc/ssl/certs

/etc/ssl/certs/ 里的文件,其实都是软链,软链到firefox 的证书目录吧,这个 /usr/share/ca-certificates/mozilla/ 。

既然如此,那我把cnnic root 的证书扔进去,总可以了吧?结果发现,还是不行的,难道是名字也有要求?格式不对?

2,朋友用mba 的curl 帮我测试,是正常的,是因为cnnic 的root 证书在信任列表吗?日后入手了mbp 再测试!

grub 和 grub2 的重建

我的小黑是双系统,windows + ubuntu ,前者用来打游戏或者网上银行,基本很少用。但无奈,最近坏了,重装了个英文版的windows 上去,要重建grub 。grub 和 grub2 的重建会稍有不同,在这里 mark 一下。

开始的步骤都一致,我是用livecd ,也可以用usb 什么的,主要是要个linux 的环境。

grub 的重建:

sudo grub  # 进入grub ,之后的操作在 grub> 的提示符下进行

find /boot/grub/menu.lst # 没有错误的话,就会返回本来装载有grub 的分区,如 (hd0,1)

root (hd0,1) # root 刚才的返回

setup (hd0) # 安装grub

quit # 退出

sudo reboot 即可

###################################

grub2 的重建:

用grub 的方法已经不可行,不过要利用一下grub 的find 功能

sudo grub # 进入grub

find /boot/grub/grub.cfg # grub2 的菜单配置文件不再是 menu.lst ,而是grub.cfg ,没有错误的话,就会返回grub2 所在的分区 , 如 (hd0,1)

quit # 退出grub

(hd0,1) 也就是第一个硬盘的第二个分区,一般是 /dev/sda2

sudo mount /dev/sda2 /mnt # 挂载之前装有 grub 的分区

sudo grub-install –root-directory=/mnt /dev/sda  # 安装grub2

ssh sftp 的设置

今天有个同事说他的 secure file transfer 使用不能。

看了下,貌似是 sshd_config 的配置有点问题,再看了下,原来是red hat 的配置用在了debian 上。

在 rh 系下,sshd_config 应该是

Subsystem       sftp    /usr/libexec/openssh/sftp-server

在 debian 下,应该是

Subsystem       sftp   /usr/lib/openssh/sftp-server

路径不一样了。。。

微博作弊

鉴于某规定,微博需要考核。

作弊是肯定的,大部分都是这样,我也是。

注册用户这个比较难,我做不了。。。手工注册的。。。

注册马甲了以后,使用以下两条语句,就可以很方便地发推了。

curl -c cookie.txt -d ‘username=&password=’ https://reg.163.com/logins.jsp
curl -b cookie.txt -d ‘status=curl test’ http://t.163.com/statuses/update.do

作弊与否,其实也不管,需要的是一个数字,数字就是绩效。哼

done, that’s all . ok, KISS .

ubuntu 10.04 初体验

想当年,我用的第一个linux 桌面是 fedora 4 ,当时就觉得这个系统实在太爽了,桌面还可以旋转,还有几个很有趣的桌面效果,哈哈,当时的想法就是傻。以致于当时以土黄色为主色调的 ubuntu 6.04 完全不进入我的考虑范围内。但,现在。。。我已经转投 ubuntu 的怀抱了。。。呃。。。唉。。。

其实两者并没有太大的区别,主要就是包管理系统的不同而已,redhat 系和 debian 系,apt-get 的资源明显多于 yum 的资源,这是我背叛 fedora 的主因,其实 ubuntu 的桌面色调我仍然十分讨厌的。

4 月30号就出了,当天就修改源, apt-get dist-upgrade 了。但很不幸,失败了,很多套件使用起来都不正常。。。唉,看来这个跨版本的升级不太靠谱,我以前也失败过,即使成功,有很多东西都是不太稳定的。只好下一个完整的install cd ,刻盘重装吧,什么硬盘重装就不折腾了。

好了,说说 10.04 主要的改进吧,呃,不能说改进,只能说是改变。

1,主色调由土黄色变成了紫色。

本来的色调给人农气的感觉,现在的色调给人艳的感觉,是一种很不喜欢的艳。这个,有点无语,不知道他们怎么想的。。。

2,窗口按钮布局变成了 MAC 系统的布局

也就是,关闭,最大化,最小化,本来是在窗口的顶部右边的,现在位于顶部左边了。UI 设计者是 MAC 爱好者??幸好我本身对 MAC 也有爱。。。

3,默认im 和 9.10 一样,是 empathy

呃。。。这个不能说不喜欢,它的对话框十分有趣,好像是抄 iphone 的那种。但是,我个人还是比较习惯 pidgin 。。。

4,broadcast 客户端

我一看,傻眼了,都是一些我们国家禁止的互联网应用阿,twitter , facebook 等,哈哈。而且我也没发现它可以设置代理。。。难道要我挂着 vpn 来上么?

5,默认黑色 theme

这个好像 9.10 也是的了,难道。。。觉得黑色的 theme 有型一点?

6,gnome-terminal 透明

这点不错,让我知道知道后面的程序的情况,例如windows 有人联系我,im 工具在闪,呵呵

7,开机关机速度

开机速度据说是经过优化的了,个人感觉不大。新装的系统嘛,通常是比较快的。。。关机速度倒是不错,比我原来的关机快多了。。。当然,也有可能是我原来的系统载入了太多垃圾。。。

才试用了几天,就先说这些把。总的来说,10.04 还是不错的,哈哈。桌面来说,还是选择 ubuntu 吧!

可恨的chrome!

chrome 其实是一个挺好的浏览器来的,在 windows 上我经常使用它(但本人不是经常使用 windows )。但这两天它带给我很大的困扰,恨死它了!!!

chrome 有 linux 版,已经是很久以前的事了,我就 download 来玩玩,平时也很少用,恰好昨天有个东西要测试,要访问杭州的节点,于是我就拿它出来,并设了一下代理服务器,在杭州搭了个 squid ,就把代理服务器设到杭州了。

印象中,以前所谓的 linux 下的 chrome 是 chromium ,这个是无法配置代理服务器的,而 官方一点的 chrome ,已经具有这个功能了,options -> under the hood -> change proxy settings ,就可以设置代理服务器了。杯具就是这样产生的了!!

我用完代理后,就顺手把 chrome 给关了,proxy setting 当然是没有改回来。

然后,从昨天一直到现在,我使用起网络来,都是怪怪的!!如:

$ curl -I lady.163.com

HTTP/1.1 200 OK
Date: Thu, 15 Apr 2010 14:44:38 GMT
Server: Apache/2.2.11 (Unix) PHP/5.3.0
Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT
ETag: “2006c2a0-2c-3e9564c23b600″
Accept-Ranges: bytes
Content-Length: 44
Content-Type: text/html

oh , my god !!

再来!

$ sudo apt-get update ;

Ign http://mirrors.163.com karmic Release.gpg
Ign http://mirrors.163.com karmic/main Translation-en_US
Ign http://mirrors.163.com karmic/restricted Translation-en_US
Ign http://mirrors.163.com karmic/multiverse Translation-en_US
Ign http://mirrors.163.com karmic/universe Translation-en_US
Ign http://mirrors.163.com karmic Release
Ign http://mirrors.163.com karmic/main Packages
Ign http://mirrors.163.com karmic/restricted Packages
Ign http://mirrors.163.com karmic/multiverse Packages
Ign http://mirrors.163.com karmic/universe Packages
Ign http://mirrors.163.com karmic/main Packages
Ign http://mirrors.163.com karmic/restricted Packages
Ign http://mirrors.163.com karmic/multiverse Packages
Ign http://mirrors.163.com karmic/universe Packages
Err http://mirrors.163.com karmic/main Packages
404  Not Found
Err http://mirrors.163.com karmic/restricted Packages
404  Not Found
Err http://mirrors.163.com karmic/multiverse Packages
404  Not Found
Err http://mirrors.163.com karmic/universe Packages
404  Not Found
W: Failed to fetch http://mirrors.163.com/ubuntu/dists/karmic/main/binary-i386/Packages.gz  404  Not Found

W: Failed to fetch http://mirrors.163.com/ubuntu/dists/karmic/restricted/binary-i386/Packages.gz  404  Not Found

W: Failed to fetch http://mirrors.163.com/ubuntu/dists/karmic/multiverse/binary-i386/Packages.gz  404  Not Found

W: Failed to fetch http://mirrors.163.com/ubuntu/dists/karmic/universe/binary-i386/Packages.gz  404  Not Found

E: Some index files failed to download, they have been ignored, or old ones used instead.

oh!! no !!!!
我一直百思不得其解!!但又太忙,就不管它了,不能curl ,就ssh 上随便一台服务器 curl 呗。而且,只要我 su 到 root ,就可以正常使用了!!我曾经怀疑,是有人黑了我的 curl 。。。还重装了 curl 呢。。。但还是出错,真是神奇了。。。

直到刚才,实在忍无可忍了!我决定彻查原因!!终于被我通过下面这条命令知道原因了!!

$ wget -S –spider lady.163.com
Spider mode enabled. Check if remote file exists.
–2010-04-15 22:48:01–  http://lady.163.com/
Connecting to 60.12.80.115:3128… connected.
Proxy request sent, awaiting response…
HTTP/1.1 200 OK
Date: Thu, 15 Apr 2010 14:48:01 GMT
Server: Apache/2.2.11 (Unix) PHP/5.3.0
Last-Modified: Sat, 20 Nov 2004 20:16:24 GMT
ETag: “2006c2a0-2c-3e9564c23b600″
Accept-Ranges: bytes
Content-Length: 44
Connection: close
Content-Type: text/html
Length: 44 [text/html]
Remote file exists and could contain further links,
but recursion is disabled — not retrieving.

fuck !! 60.12.80.115:3128 是我在杭州的代理!!原来修改 chrome 的 network 配置,还影响了我平时的网络使用!!fuck !!!

debian 下 ssh 更改 gnome-terminal 的 title

我的工作环境,一般在 rh 系和 debian 系中切换,毕竟是不同的产品,细微的不同很容易令到人昏头转向的。我的工作用机,ubuntu,gnome-terminal 就是我的日常必备工具了,而使用 gnome-terminal ssh 上rh 和 debian 的机器,就可以通过gnome terminal 的 title ,很快分辨出我登录的是哪个系统的机器了。

如:ssh rh 的机器,title 显示的是 ” lazybug@yz12-67 ~ ” ,这个是远程的系统信息。而登录 debian 的机器呢,显示 ” czbug@thinkpad-laptop: ~ “,无论登录哪台,都是一样的显示,因为这是本地的。

关键在于 shell 的一个变量,可以通过命令 set 看到(env 和 set 是有区别的,详情请 google ):

PROMPT_COMMAND=’echo -ne “\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\007″‘

rh 是有上面这个变量的,而 debian 没有。

好了,如果我们想让 debian 也像rh 那样显示呢??加上这个变量呗,在 /etc/profile 里加上下面这段:

case $TERM in
(xterm*)
PROMPT_COMMAND=’echo -ne “\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\007″‘
;;
esac
没有root 权限的话,加在 ~/.profile 也行