畅谈linux下TCP(上)

畅谈linux下TCP(上),第1张

tcp 协议 是互联网中最常用的协议 , 开发人员基本上天天和它打交道,对它进行深入了解。 可以帮助我们排查定位bug和进行程序优化。下面我将就TCP几个点做深入的探讨

客户端:收到 ack 后 分配连接资源。 发送数据

服务器 : 收到 syn 后立即 分配连接资源

客户端:收到ACK, 立即分配资源

服务器:收到ACK, 立即分配资源

既然三次握手也不是100%可靠, 那四次,五次,六次。。。呢? 其实都一样,不管多少次都有丢包问题。

client 只发送一个 SYN, server 分配一个tcb, 放入syn队列中。 这时候连接叫 半连接 状态;如果server 收不到 client 的ACK, 会不停重试 发送 ACK-SYN 给client 。重试间隔 为 2 的 N 次方 叠加(2^0 , 2^1, 2^2 ....);直至超时才释放syn队列中的这个 TCB

在半连接状态下, 一方面会占用队列配额资源,另一方面占用内存资源。我们应该让半连接状态存在时间尽可能的小

当client 向一个未打开的端口发起连接请求时,会收到一个RST回复包

当listen 的 backlog 和 somaxconn 都设置了得时候, 取两者min值

Recv-Q 是accept 队列当前个数, Send-Q 设置最大值

这种SYN洪水攻击是一种常见攻击方式,就是利用半连接队列特性,占满syn 队列的 资源,导致 client无法连接上。

解决方案:

为什么不像握手那样合并成三次挥手? 因为和刚开始连接情况,连接是大家都从0开始, 关闭时有历史包袱的。server(被动关闭方) 收到 client(主动关闭方) 的关闭请求FIN包。 这时候可能还有未发送完的数据,不能丢弃。 所以需要分开。事实可能是这样

当然,在没有待发数据,并且允许 Delay ACK 情况下, FIN-ACK合并还是非常常见的事情,这是三次挥手是可以的。

同上

CLOSE_WAIT 是被动关闭方才有的状态

被动关闭方 [收到 FIN 包 发送 ACK 应答] 到 [发送FIN, 收到ACK ] 期间的状态为 CLOSE_WAIT, 这个状态仍然能发送数据。 我们叫做 半关闭 , 下面用个例子来分析:

这个是我实际生产环境碰到的一个问题,长连接会话场景,server端收到client的rpc call 请求1,处理发现请求包有问题,就强制关闭结束这次会话, 但是 因为client 发送 第二次请求之前,并没有去调用recv,所以并不知道 这个连接被server关闭, 继续发送 请求2 , 此时是半连接,能够成功发送到对端机器,但是recv结果后,遇到连接已经关闭错误。

如果 client 和 server 恰好同时发起关闭连接。这种情况下,两边都是主动连接,都会进入 TIME_WAIT状态

1、 被动关闭方在LAST_ACK状态(已经发送FIN),等待主动关闭方的ACK应答,但是 ACK丢掉, 主动方并不知道,以为成功关闭。因为没有TIME_WAIT等待时间,可以立即创建新的连接, 新的连接发送SYN到前面那个未关闭的被动方,被动方认为是收到错误指令,会发送RST。导致创建连接失败。

2、 主动关闭方断开连接,如果没有TIME_WAIT等待时间,可以马上建立一个新的连接,但是前一个已经断开连接的,延迟到达的数据包。 被新建的连接接收,如果刚好seq 和 ack字段 都正确, seq在滑动窗口范围内(只能说机率非常小,但是还是有可能会发生),会被当成正确数据包接收,导致数据串包。 如果不在window范围内,则没有影响( 发送一个确认报文(ack 字段为期望ack的序列号,seq为当前发送序列号),状态变保持原样)

TIME_WAIT 问题比较比较常见,特别是CGI机器,并发量高,大量连接后段服务的tcp短连接。因此也衍生出了多种手段解决。虽然每种方法解决不是那么完美,但是带来的好处一般多于坏处。还是在日常工作中会使用。

1、改短TIME_WAIT 等待时间

这个是第一个想到的解决办法,既然等待时间太长,就改成时间短,快速回收端口。但是实际情况往往不乐观,对于并发的机器,你改多短才能保证回收速度呢,有时候几秒钟就几万个连接。太短的话,就会有前面两种问题小概率发生。

2、禁止Socket lingering

这种情况下关闭连接,会直接抛弃缓冲区中待发送的数据,会发送一个RST给对端,相当于直接抛弃TIME_WAIT, 进入CLOSE状态。同样因为取消了 TIME_WAIT 状态,会有前面两种问题小概率发生。

3、tcp_tw_reuse

net.ipv4.tcp_tw_reuse选项是 从 TIME_WAIT 状态的队列中,选取条件:1、remote 的 ip 和端口相同, 2、选取一个时间戳小于当前时间戳; 用来解决端口不足的尴尬。

现在端口可以复用了,看看如何面对前面TIME_WAIT 那两种问题。 我们仔细回顾用一下前面两种问题。 都是在新建连接中收到老连接的包导致的问题 , 那么如果我能在新连接中识别出此包为非法包,是不是就可以丢掉这些无用包,解决问题呢。

需要实现这些功能,需要扩展一下tcp 包头。 增加 时间戳字段。 发送者 在每次发送的时候。 在tcp包头里面带上发送时候的时间戳。 当接收者接收的时候,在ACK应答中除了TCP包头中带自己此时发送的时间戳,并且把收到的时间戳附加在后面。也就是说ACK包中有两个时间戳字段。结构如下:

那我们接下来一个个分析tcp_tw_reuse是如何解决TIME_WAIT的两个问题的

4、tcp_tw_recycle

tcp_tw_recycle 也是借助 timestamp机制。顾名思义, tcp_tw_reuse 是复用 端口,并不会减少 TIME-WAIT 数量。你去查询机器上TIME-WAIT 数量,还是 几千几万个,这点对有强迫症的同学感觉很不舒服。tcp_tw_recycle 是 提前 回收 TIME-WAIT资源。会减少 机器上 TIME-WAIT 数量。

tcp_tw_recycle 工作原理是。

一. FTP 说明 linux 系统下常用的FTP 是vsftp, 即Very Security File Transfer Protocol. 还有一个是proftp(Profession ftp)。 我们这里也是简单的说明下vsftp的配置。 vsftp提供3种远程的登录方式: (1)匿名登录方式 就是不需要用户名,密码。就能登录到服务器电脑里面(2)本地用户方式 需要帐户名和密码才能登录。而且,这个帐户名和密码,都是在你linux系统里面,已经有的用户。 (3)虚拟用户方式 同样需要用户名和密码才能登录。但是和上面的区别就是,这个用户名和密码,在你linux系统中是没有的(没有该用户帐号)二. Vsftp的安装配置2.1 安装vsftp 的安装包,可以在安装里找到。 用yum 安装过程也很简单。 安装命令:yum install vsftpd2.2. 相关命令2.2.1 启动与关闭[root@singledb ~]# service vsftpd startStarting vsftpd for vsftpd:[ OK ][root@singledb ~]# service vsftpd stopShutting down vsftpd: [ OK ][root@singledb ~]# service vsftpd restartShutting down vsftpd: [FAILED]Starting vsftpd for vsftpd:[ OK ][root@singledb ~]# /etc/init.d/vsftpd startStarting vsftpd for vsftpd:[FAILED][root@singledb ~]# /etc/init.d/vsftpd stopShutting down vsftpd: [ OK ][root@singledb ~]# /etc/init.d/vsftpd restartShutting down vsftpd: [FAILED]Starting vsftpd for vsftpd:[ OK ][root@singledb ~]# /etc/init.d/vsftpd statusvsftpd (pid 3931) is running...[root@singledb ~]#2.2.2. 其他命令--查看vsftpd 启动状态[root@singledb ~]# chkconfig --list vsftpdvsftpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off[root@singledb ~]# chkconfig vsftpd on[root@singledb ~]# chkconfig --list vsftpdvsftpd 0:off 1:off 2:on3:on4:on5:on6:off 这里看到,默认情况下从2到5设置为on了。2到5是多用户级别。 这个对应的是linux不同的运行级别。我们也可以加level 选项来指定:[root@singledb ~]# chkconfig --level 0 vsftpd on [root@singledb ~]# chkconfig --list vsftpd vsftpd 0:on1:off 2:on3:on4:on5:on6:off我们看到0已经设置为on了。我们可以使用man chkconfig 来查看帮助:--level levelsSpecifies the run levels an operation should pertain to. It is given as a string of numbers from 0 to 7. For example, --level 35 specifies runlevels 3 and 5. 传统的init 定义了7个运行级(run level),每一个级别都代表系统应该补充运行的某些特定服务: (1)0级是完全关闭系统的级别 (2)1级或者S级代表单用户模式 (3)2-5 级 是多用户级别 (4)6级 是 重新引导的级别(1)查看防火墙我一般都是把系统的防火墙关闭了。 因为开了会有很多限制。[root@singledb ~]# /etc/init.d/iptables statusTable: natChain PREROUTING (policy ACCEPT)num target prot opt source destinationChain POSTROUTING (policy ACCEPT)num target prot opt source destination1MASQUERADE all -- 192.168.122.0/24!192.168.122.0/24 Chain OUTPUT (policy ACCEPT)num target prot opt source destination Table: filterChain INPUT (policy ACCEPT)num target prot opt source destination1ACCEPT udp -- 0.0.0.0/00.0.0.0/0 udp dpt:532ACCEPT tcp -- 0.0.0.0/00.0.0.0/0 tcp dpt:533ACCEPT udp -- 0.0.0.0/00.0.0.0/0 udp dpt:674ACCEPT tcp -- 0.0.0.0/00.0.0.0/0 tcp dpt:67Chain FORWARD (policy ACCEPT)num target prot opt source destination1ACCEPT all -- 0.0.0.0/0192.168.122.0/24state RELATED,ESTABLISHED2ACCEPT all -- 192.168.122.0/24 0.0.0.0/0 3ACCEPT all -- 0.0.0.0/00.0.0.0/0 4REJECT all -- 0.0.0.0/00.0.0.0/0 reject-with icmp-port-unreachable5REJECT all -- 0.0.0.0/00.0.0.0/0 reject-with icmp-port-unreachableChain OUTPUT (policy ACCEPT)num target prot opt source destinationYou have new mail in /var/spool/mail/root--添加开放21号端口:[root@singledb ~]# /sbin/iptables -I INPUT -p tcp --dport 21 -j ACCEPT[root@singledb ~]# /etc/init.d/iptables statusTable: natChain PREROUTING (policy ACCEPT)num target prot opt source destination Chain POSTROUTING (policy ACCEPT)num target prot opt source destination1MASQUERADE all -- 192.168.122.0/24!192.168.122.0/24 Chain OUTPUT (policy ACCEPT)num target prot opt source destinationTable: filterChain INPUT (policy ACCEPT)num target prot opt source destination1ACCEPT tcp -- 0.0.0.0/00.0.0.0/0 tcp dpt:212ACCEPT udp -- 0.0.0.0/00.0.0.0/0 udp dpt:533ACCEPT tcp -- 0.0.0.0/00.0.0.0/0 tcp dpt:534ACCEPT udp -- 0.0.0.0/00.0.0.0/0 udp dpt:675ACCEPT tcp -- 0.0.0.0/00.0.0.0/0 tcp dpt:67Chain FORWARD (policy ACCEPT)num target prot opt source destination1ACCEPT all -- 0.0.0.0/0192.168.122.0/24state RELATED,ESTABLISHED2ACCEPT all -- 192.168.122.0/24 0.0.0.0/0 3ACCEPT all -- 0.0.0.0/00.0.0.0/0 4REJECT all -- 0.0.0.0/00.0.0.0/0 reject-with icmp-port-unreachable5REJECT all -- 0.0.0.0/00.0.0.0/0 reject-with icmp-port-unreachableChain OUTPUT (policy ACCEPT)num target prot opt source destination--保存配置[root@singledb ~]# /etc/rc.d/init.d/iptables saveSaving firewall rules to /etc/sysconfig/iptables: [ OK ]--重启防火墙:[root@singledb ~]# service iptables {startstoprestart}(2)查看关闭selinux[root@singledb ~]# sestatusSELinux status: disabled我这里在安装 *** 作系统的时候就关闭了selinux,如果没有关闭,可以修改如下文件来关闭:[root@singledb ~]# cat /etc/sysconfig/selinux# This file controls the state of SELinux on the system.# SELINUX= can take one of these three values:# enforcing - SELinux security policy is enforced.# permissive - SELinux prints warnings instead of enforcing.# disabled - SELinux is fully disabled.SELINUX=disabled# SELINUXTYPE= type of policy in use. Possible values are:# targeted - Only targeted network daemons are protected.# strict - Full SELinux protection.SELINUXTYPE=targeted[root@singledb ~]#保存退出并重启系统reboot三. FTP配置文件FTP 安装好之后,在/etc/vsftpd/目录下会有如下文件:[root@singledb ~]# cd /etc/vsftpd/[root@singledb vsftpd]# lsftpusers user_list vsftpd.conf vsftpd_conf_migrate.sh[root@singledb vsftpd]#vsftpd.conf: 主配置文件ftpusers: 指定哪些用户不能访问FTP服务器user_list: 指定的用户是否可以访问ftp服务器由vsftpd.conf文件中的userlist_deny的取值来决定。[root@singledb vsftpd]# cat user_list# vsftpd userlist# If userlist_deny=NO, only allow users in this file# If userlist_deny=YES (default), never allow users in this file, and# do not even prompt for a password.# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers# for users that are denied.我们过滤掉#的注释后,查看一下vsftpd.conf 文件:[root@singledb ftp]# cat /etc/vsftpd/vsftpd.conf grep -v '^#'anonymous_enable=YESlocal_enable=YESwrite_enable=YESlocal_umask=022dirmessage_enable=YESxferlog_enable=YESconnect_from_port_20=YESxferlog_std_format=YESlisten=YESpam_service_name=vsftpduserlist_enable=yestcp_wrappers=YES至于这些参数的意思,在注释里有详细的说明。我们可以在vsftpd.conf 文件设置如下参数:(1)ftpd_banner=welcome to ftp service :设置连接服务器后的欢迎信息(2)idle_session_timeout=60 :限制远程的客户机连接后,所建立的控制连接,在多长时间没有做任何的 *** 作就会中断(秒)(3)data_connection_timeout=120 :设置客户机在进行数据传输时,设置空闲的数据中断时间(4)accept_timeout=60 设置在多长时间后自动建立连接(5)connect_timeout=60 设置数据连接的最大激活时间,多长时间断开,为别人所使用(6)max_clients=200 指明服务器总的客户并发连接数为200(7)max_per_ip=3 指明每个客户机的最大连接数为3(8)local_max_rate=50000(50kbytes/sec) 本地用户最大传输速率限制(9)anon_max_rate=30000匿名用户的最大传输速率限制(10)pasv_min_port=端口(11)pasv-max-prot=端口号 定义最大与最小端口,为0表示任意端口为客户端连接指明端口(12)listen_address=IP地址 设置ftp服务来监听的地址,客户端可以用哪个地址来连接(13)listen_port=端口号 设置FTP工作的端口号,默认的为21(14)chroot_local_user=YES 设置所有的本地用户可以chroot(15)chroot_local_user=NO 设置指定用户能够chroot(16)chroot_list_enable=YES(17)chroot_list_file=/etc/vsftpd/chroot_list(只有/etc/vsftpd/chroot_list中的指定的用户才能执行 )(18)local_root=path 无论哪个用户都能登录的用户,定义登录帐号的主目录, 若没有指定,则每一个用户则进入到个人用户主目录(19)chroot_local_user=yes/no 是否锁定本地系统帐号用户主目录(所有)锁定后,用户只能访问用户的主目录/home/user,不能利用cd命令向上转只能向下(20)chroot_list_enable=yes/no 锁定指定文件中用户的主目录(部分),文件:/chroot_list_file=path 中指定(21)userlist_enable=YES/NO 是否加载用户列表文件(22)userlist_deny=YES 表示上面所加载的用户是否允许拒绝登录(23)userlist_file=/etc/vsftpd/user_list 列表文件限制IP 访问FTP:#vi /etc/hosts.allowvsftpd:192.168.5.128:DENY 设置该IP地址不可以访问ftp服务FTP 访问时间限制:#cp /usr/share/doc/vsftpd-1.1.3/vsftpd.xinetd /etc/xinetd.d/vsftpd#vi /etc/xinetd.d/vsftpd/修改 disable = noaccess_time = hour:min-hour:min (添加配置访问的时间限制(注:与vsftpd.conf中listen=NO相对应)例: access_time = 8:30-11:30 17:30-21:30 表示只有这两个时间段可以访问ftpftp的配置基本上只有这些了。 默认情况下,ftp根目录是/var/ftp。 如果要修改这个目录位置,可以更改/etc/passwd 文件:[root@singledb ftp]# cat /etc/passwd grep ftpftp:x:14:50:FTP User:/var/ftp:/sbin/nologin创建一个用户来访问FTP,并指定该用户的FTP 目录:[root@singledb u02]# useradd -d /u02/qsftp qs[root@singledb u02]# passwd qsChanging password for user qs.New UNIX password:BAD PASSWORD: it is WAY too shortRetype new UNIX password:passwd: all authentication tokens updated successfully.这里指定的是/u02/qsftp 这个目录,要注意个目录的权限。更改用户不能telnet,只能ftp: usermod -s /sbin/nologin username //用户只能ftp,不能telnet usermod -s /sbin/bash username //用户恢复正常禁止用户ssh登陆 useradd username -s /bin/false 更改用户主目录: usermod -d /bbb username//把用户的主目录定为/bbb然后用qs这个用户就可以访问了。 以上只是一些简单的设置。 在用户权限这块还有很多内容可以研究。 比如特定用户的特定权限。 安全性等。 以后在研究了。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7243916.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-03
下一篇 2023-04-03

发表评论

登录后才能评论

评论列表(0条)

保存