kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp
sar -n DEV 1

SYN cookies机制下连接的建立

http://blog.csdn.net/justlinux2010/article/details/12619761

在正常情况下,服务器端接收到客户端发送的SYN包,会分配一个连接请求块(即request_sock结构),用于保存连接请求信息,并且发送SYN+ACK包给客户端,然后将连接请求块添加到半连接队列中。客户端接收到SYN+ACK包后,会发送ACK包对服务器端的包进行确认。服务器端收到客户端的确认后,根据保存的连接信息,构建一个新的连接,放到监听套接字的连接队列中,等待用户层accept连接。这是正常的情况,但是在并发过高或者遭受SYN flood攻击的情况下,半连接队列的槽位数量很快就会耗尽,会导致丢弃新的连接请求,SYN cookies技术可以使服务器在半连接队列已满的情况下仍能处理新的SYN请求。

如果开启了SYN cookies选项,在半连接队列满时,SYN cookies并不丢弃SYN请求,而是将源目的IP、源目的端口号、接收到的客户端初始序列号以及其他一些安全数值等信息进行hash运算,并加密后得到服务器端的初始序列号,称之为cookie。服务器端在发送初始序列号为cookie的SYN+ACK包后,会将分配的连接请求块释放。如果接收到客户端的ACK包,服务器端将客户端的ACK序列号减1得到的值,与上述要素hash运算得到的值比较,如果相等,直接完成三次握手,构建新的连接。SYN cookies机制的核心就是避免攻击造成的大量构造无用的连接请求块,导致内存耗尽,而无法处理正常的连接请求。

启用SYN cookies是通过在启动环境中设置以下命令完成:

1
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

注意,即使开启该机制并不意味着所有的连接都是用SYN cookies机制来完成连接的建立,只有在半连接队列已满的情况下才会触发SYN cookies机制。由于SYN cookies机制严重违背TCP协议,不允许使用TCP扩展,可能对某些服务造成严重的性能影响(如SMTP转发),对于防御SYN flood攻击的确有效。对于没有收到攻击的高负载服务器,不要开启此选项,可以通过修改tcp_max_syn_backlog、tcp_synack_retries和tcp_abort_on_overflow系统参数来调节。

下面来看看内核中是怎么通过SYN cookie机制来完成连接的建立。

客户端的连接请求由

1
2
3
4
tcp_v4_do_rcv()
	tcp_rcv_state_process()
		icsk->icsk_af_ops->conn_request()
			tcp_v4_conn_request()

函数处理。tcp_v4_conn_request()中有一个局部变量want_cookie,用来标识是否使用SYN cookies机制。want_cookie的初始值为0,如果半连接队列已满,并且开启了tcp_syncookies系统参数,则将其值设置为1,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
#ifdef CONFIG_SYN_COOKIES
	int want_cookie = 0;
#else
#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
#endif

...... 

	/* TW buckets are converted to open requests without
	 * limitations, they conserve resources and peer is
	 * evidently real one.
	 */
	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
#ifdef CONFIG_SYN_COOKIES
		if (sysctl_tcp_syncookies) {
			want_cookie = 1;
		} else
#endif
	   
		goto drop;
	}
......

drop:
	return 0;
}

如果没有开启SYN cookies机制,在半连接队列满时,会跳转到drop处,返回0。在调用tcp_v4_conn_request()的tcp_rcv_state_process()中会直接释放SKB包。

我们前面提高过,造成半连接队列满有两种情况(不考虑半连接队列很小的情况),一种是负载过高,正常的连接数过多;另一种是SYN flood攻击。如果是第一种情况,此时是否继续构建连接,则要取决于连接队列的情况及半连接队列的重传情况,如下所示:

1
2
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
	goto drop;

sk_acceptq_is_full()函数很好理解,根据字面意思就可以看出,该函数是检查连接队列是否已满。inet_csk_reqsk_queue_young()函数返回半连接队列中未重传过SYN+ACK段的连接请求块数量。如果连接队列已满并且半连接队列中的连接请求块中未重传的数量大于1,则会跳转到drop处,丢弃SYN包。如果半连接队列中未重传的请求块数量大于1,则表示未来可能有2个完成的连接,这些新完成的连接要放到连接队列中,但此时连接队列已满。如果在接收到三次握手中最后的ACK后连接队列中没有空闲的位置,会忽略接收到的ACK包,连接建立会推迟,所以此时最好丢掉部分新的连接请求,空出资源以完成正在进行的连接建立过程。还要注意,这个判断并没有考虑半连接队列是否已满的问题。从这里可以看出,即使开启了SYN cookies机制并不意味着一定可以完成连接的建立。

如果可以继续连接的建立,调用inet_reqsk_alloc()分配连接请求块,如下所示:

1
2
3
req = inet_reqsk_alloc(&tcp_request_sock_ops);
if (!req)
	goto drop;

看到这里可能就有人疑惑,既然开启了SYN cookies机制,仍然分配连接请求块,那和正常的连接构建也没有什么区别了。这里之所以要分配连接请求块是用于发送SYN+ACK包给客户端,发送后会释放掉,并不会加入到半连接队列中。

接下来就是计算cookie的值,由cookie_v4_init_sequence()函数完成,如下所示:

1
2
3
4
5
6
7
if (want_cookie) {
#ifdef CONFIG_SYN_COOKIES
	syn_flood_warning(skb);
	req->cookie_ts = tmp_opt.tstamp_ok;
#endif
	isn = cookie_v4_init_sequence(sk, skb, &req->mss);
}

计算得到的cookie值会保存在连接请求块tcp_request_sock结构的snt_isn成员中,接着会调用__tcp_v4_send_synack()函数发送SYN+ACK包,然后释放前面分配的连接请求块,如下所示:

1
2
if (__tcp_v4_send_synack(sk, req, dst) || want_cookie)
	goto drop_and_free;

在服务器端发送完SYN+ACK包后,我们看到在服务器端没有保存任何关于这个未完成连接的信息,所以在接收到客户端的ACK包后,只能根据前面发送的SYN+ACK包中的cookie值来决定是否继续构建连接。

我们接下来看接收到ACK包后的处理情况。ACK包在tcp_v4_do_rcv()函数中调用的tcp_v4_hnd_req()中处理,如下所示:

1
2
3
4
5
6
7
8
9
10
static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
{
	......
 
#ifdef CONFIG_SYN_COOKIES
	if (!th->rst && !th->syn && th->ack)
		sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
#endif
	return sk;
}

由于在服务器端没有保存未完成连接的信息,所以在半连接队列或ehash散列表中都不会找到对应的sock结构。如果开启了SYN cookies机制,则会检查接收到的数据包是否是ACK包,如果是,在cookie_v4_check()中会调用cookie_check()函数检查ACK包中的cookie值是否有效。如果有效,则会分配request_sock结构,并根据ACK包初始化相应的成员,开始构建描述连接的sock结构。创建过程和正常的连接创建过程一样。

CentOS各种设置

centos个人目录文件夹路径中文转英文

方法1. 修改系统语言环境

1
2
3
export LANG=en_US
xdg-user-dirs-gtk-update
export LANG=zh_CN.UTF-8

方法2. 修改系统配置文件

1
vim ~/.config/user-dirs.dirs

centos 8 重启网络命令

https://blog.csdn.net/weixin_54626591/article/details/135974971

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nmcli c reload ens33        (不会立即生效)  # 重新载入网卡配置文件

nmcli c up ens33            (立即生效)      # 重启网卡ens33

两条命令一起执行, 如果不行,可尝试以下命令

# 重载所有ifcfg或route到connection(不会立即生效)
nmcli c reload  ifcfg-xxx

# 重载指定ifcfg或route到connection(不会立即生效)
nmcli c load etc/sysconfig/network-scripts/ifcfg-ethX
nmcli c load etc/sysconfig/network-scripts/route-ethX

# 立即生效connection,有3种方法
nmcli c up ethX
nmcli d reapply ethX
nmcli d connect ethX

Centos7系统rc.local不起作用

chmod +x /etc/rc.d/rc.local

开头加 #!/bin/bash

启动此项服务:

systemctl list-units –type=service #来查看一下所有的开启启动项目里面有没有这个rc-local这个服务。

systemctl status rc-local.service #来查看一下当前是怎么个状态

systemctl enable rc-local.service

systemctl start rc-local.service


使用gcc时,总是按中文提示。回归英文的提示,方法是: 首先使用env查看,发现LANGUAGE=zh_CN.UTF-8,接着执行export LANG=en_US.UTF-8就可以,以后的编译是就按英文来提示


1
2
lsattr /etc/passwd /etc/group /etc/shadow /etc/gshadow
chattr -i /etc/passwd /etc/group /etc/shadow /etc/gshadow

英文:E437: terminal capability “cm” required
中文:e437 终端需要能力 cm

这个错误一般是环境变量TERM没有配置或者配置错误所致, 用 export TERM=linux 或者 export TERM=xterm


上传是用rz -be,并且去掉弹出的对话框中“Upload files as ASCII”前的勾选。 -a, –ascii -b, –binary 用binary的方式上传下载,不解释字符为ascii -e, –escape 强制escape 所有控制字符,比如Ctrl+x,DEL等


nginx

http://nginx.org/packages/rhel/7/x86_64/RPMS/


binkernel.spec

1
2
3
4
5
6
7
8
9
10
11
12
%pre
mkdir -p /usr/local/kernel/etc/
echo "version=%{version}-%{release}" > /usr/local/kernel/etc/install.conf

%post
/sbin/new-kernel-pkg --package kernel --mkinitrd --depmod --install 2.6.32-358.6.1.ws5.b.5.1.11t25

%preun
rm -rf /usr/local/kernel/

%postun
/sbin/new-kernel-pkg  --remove 2.6.32-358.6.1.ws5.b.5.1.11t25

更改 bash_history 默认历史记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
vim ~/.bashrc

# 忽略[连续]重复命令
HISTCONTROL=ignoredups

# 清除重复命令
# HISTCONTROL=erasedups

# 忽略特定命令
HISTIGNORE="[   ]*:ls:ll:cd:vi:pwd:sync:exit:history*"

# 命令历史文件大小10M
HISTFILESIZE=1000000000

# 保存历史命令条数10W
HISTSIZE=1000000

以上配置可以通过 set | grep HIST 查看可选项.


多终端追加
当打开多个终端,关闭其中一个终端时会覆盖其他终端的命令历史,这里我们采用追加的方式避免命令历史文件.bash_history 文件被覆盖。

shopt -s histappend

更多 shopt 可选项可以通过 echo $SHELLOPTS 命令查看。

关闭CentOS6启动进度条,显示详细自检信息。vim /boot/grub/grub.conf,将"rhgb"和 “quiet"去掉,保存即可


vmware虚拟机mkinitrd提示no module ehci-hcd 错误的话,加:

1
--builtin=ehci-hcd --builtin=ohci-hcd --builtin=uhci-hcd

CentOS6.0 下默认开selinux时出现httpd 报“SELinux policy enabled; httpd running as context unconfined_u:system”的解决方案

1
2
3
4
5
yum install policycoreutils-python

# To allow httpd to use nfs dirs in CentOS-6
setsebool -P httpd_use_nfs 1
setsebool -P httpd_enable_homedirs 1

CentOS 关闭防火墙

1) 永久性生效,重启后不会复原
开启:

1
2
chkconfig iptables on
chkconfig ip6tables on

关闭:

1
2
chkconfig iptables off
chkconfig ip6tables off

2) 即时生效,重启后复原
开启:

1
2
service iptables start
service ip6tables start

关闭:

1
2
service iptables stop
service ip6tables stop

CentOS安装软件:/lib/ld-linux.so.2: bad ELF interpreter 解决

是因为64位系统中安装了32位程序, 解决方法:

1
yum install glibc.i686

其他包

1
yum install libstdc++.i686

gcc, c++

1
2
3
4
yum install glibc
yum install glibc-devel
yum install gcc-c++
yum install libstdc++

tc模拟丢包率时延

tc 的最最基本的使用

1
2
3
4
tc qdisc show    # 显示
tc qdisc add dev eth0 root ...... # 加入
tc qdisc change dev eth0 root ...... # 修改存在的 qdisc ,记的,加入同一条后只能用 change 来修改
tc qdisc del dev eth0 root  # 删除

Linux 中延时模拟

设置延时 3s :

1
tc qdisc add dev eth0 root netem delay 3000ms

可以在 3000ms 后面在加上一个延时,比如 3000ms 200ms 表示 3000ms ± 200ms ,延时范围 2800 – 3200 之间.

Linux 中丢包模拟

设置丢包 50% ,iptables 也可以模拟这个,但一下不记的命令了,下次放上来:

1
tc qdisc change dev eth0 root netem loss 50%

上面的设丢包,如果给后面的 50% 的丢包比率修改成 50% 80% 时,这时和上面的延时不一样,这是指丢包比率为 50-80% 之间。