linux系统telnet端口不通能收到SYN但不回SYN+ACK响应问题排查

一:背景:
一台机器从公司办公网登录不上且所有tcp端口都telnet不通,但是通过同机房同的其它机器却可以正常访问到出问题的机器。于是就立即在这台出问题的server端抓包分析,发现问题如下:
server端收到了本地pc发的SYN包,但是没有回syn+ack包,所以确认是server端系统问题。tcpdump抓包如下:


client端抓包:
有发送,服务端回的都是R 重置
[root@localhost ~]# tcpdump -vv host 1.1.1.1
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:56:47.156700 IP (tos 0x10, ttl 64, id 58127, offset 0, flags [DF], proto TCP (6), length 60)
10.10.18.161.59860 > 1.1.1.1.ftp: Flags [S], cksum 0xda7b (correct), seq 2448459144, win 14600, options [mss 1460,sackOK,TS val 4000933511 ecr 0,nop,wscale 7], length 0
14:56:48.156592 IP (tos 0x10, ttl 64, id 58128, offset 0, flags [DF], proto TCP (6), length 60)
10.10.18.161.59860 > 1.1.1.1.ftp: Flags [S], cksum 0xd693 (correct), seq 2448459144, win 14600, options [mss 1460,sackOK,TS val 4000934511 ecr 0,nop,wscale 7], length 0
14:56:53.881707 IP (tos 0x0, ttl 252, id 63006, offset 0, flags [DF], proto TCP (6), length 40)
1.1.1.1.ftp > 10.10.18.161.59860: Flags [R.], cksum 0xd054 (correct), seq 0, ack 2448459145, win 0, length 0

14:58:57.481680 IP (tos 0x10, ttl 64, id 25165, offset 0, flags [DF], proto TCP (6), length 60)
10.10.18.161.56634 > 1.1.1.1.rsync: Flags [S], cksum 0x8df0 (correct), seq 1851916753, win 14600, options [mss 1460,sackOK,TS val 4001063836 ecr 0,nop,wscale 7], length 0
14:58:58.481605 IP (tos 0x10, ttl 64, id 25166, offset 0, flags [DF], proto TCP (6), length 60)
10.10.18.161.56634 > 1.1.1.1.rsync: Flags [S], cksum 0x8a08 (correct), seq 1851916753, win 14600, options [mss 1460,sackOK,TS val 4001064836 ecr 0,nop,wscale 7], length 0
14:59:08.587051 IP (tos 0x0, ttl 252, id 14708, offset 0, flags [DF], proto TCP (6), length 40)
1.1.1.1.rsync > 10.10.18.161.56634: Flags [R.], cksum 0x80e0 (correct), seq 0, ack 1851916754, win 0, length 0

server端抓包
只能收到类似下面的发过来的包,没有响应包
# tcpdump -n -vv -i eth0 tcp port 21
00:04:43.585345 IP (tos 0x14, ttl 47, id 50536, offset 0, flags [DF], proto TCP (6), length 52)
121.15.134.170.32581 > 172.18.54.135.ftp: Flags [F.], cksum 0x341d (correct), seq 1, ack 77, win 58, options [nop,nop,TS val 4071735193 ecr 877988392], length 0
00:04:43.585457 IP (tos 0x0, ttl 64, id 17336, offset 0, flags [DF], proto TCP (6), length 52)
172.18.54.135.ftp > 121.15.134.170.32581: Flags [.], cksum 0xe279 (incorrect -> 0xd9f8), seq 77, ack 2, win 57, options [nop,nop,TS val 878011469 ecr 4071735193], length 0
00:04:43.585489 IP (tos 0x0, ttl 64, id 17337, offset 0, flags [DF], proto TCP (6), length 52)
172.18.54.135.ftp > 121.15.134.170.32581: Flags [F.], cksum 0xe279 (incorrect -> 0xd9f7), seq 77, ack 2, win 57, options [nop,nop,TS val 878011469 ecr 4071735193], length 0
00:04:43.591892 IP (tos 0x14, ttl 47, id 12870, offset 0, flags [DF], proto TCP (6), length 52)
121.15.134.170.32581 > 172.18.54.135.ftp: Flags [.], cksum 0xd9f0 (correct), seq 2, ack 78, win 58, options [nop,nop,TS val 4071735199 ecr 878011469], length 0

二,排查

1,发现系统没有任何负载

2,网卡也没有丢包

3,iptables策略也都没问题

4,系统的SYN_RECV连接很少,也没超限

5,系统的文件描述符等资源也都没问题

6,messages和dmesg中没有任何提示或者错误信息

7,通过netstat命令查看系统上协议统计信息,发现很多请求由于时间戳的问题被rejected

# netstat -s |grep reject
2092 passive connections rejected because of time stamp
1506 packets rejects in established connections because of timestamp

三,通过google来协助

发现有同样的人遇见这个问题:

是通过调整sysctl -w net.ipv4.tcp_timestamps=0或者sysctl -w net.ipv4.tcp_tw_recycle=0来解决这个问题,于是我就顺藤摸瓜继续查。

而在查询这两个参数的过程中,发现问题原因如下:

发现是 Linux tcp_tw_recycle/tcp_timestamps设置导致的问题。 因为在linux kernel源码中发现tcp_tw_recycle/tcp_timestamps都开启的条件下,60s内同一源ip主机的socket connect请求中的timestamp必须是递增的。经过测试,我这边centos6系统(kernel 2.6.32)和centos7系统(kernel 3.10.0)都有这问题。

源码函数:kernel 2.6.32 tcp_v4_conn_request(),该函数是tcp层三次握手syn包的处理函数(服务端);
源码片段:
if (tmp_opt.saw_tstamp &&
tcp_death_row.sysctl_tw_recycle &&
(dst = inet_csk_route_req(sk, req)) != NULL &&
(peer = rt_get_peer((struct rtable *)dst)) != NULL &&
peer->v4daddr == saddr) {
if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
(s32)(peer->tcp_ts - req->ts_recent) >
TCP_PAWS_WINDOW) {
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
goto drop_and_release;
}
}

tmp_opt.saw_tstamp:该socket支持tcp_timestamp
sysctl_tw_recycle:本机系统开启tcp_tw_recycle选项
TCP_PAWS_MSL:60s,该条件判断表示该源ip的上次tcp通讯发生在60s内
TCP_PAWS_WINDOW:1,该条件判断表示该源ip的上次tcp通讯的timestamp 大于 本次tcp

总结:

我这边和其它同事通过公司出口(NAT网关只有1个ip地址)访问问题server,由于timestamp时间为系统启动到当前的时间,故我和其它同事的timestamp肯定不相同;根据上述SYN包处理源码,在tcp_tw_recycle和tcp_timestamps同时开启的条件下,timestamp大的主机访问serverN成功,而timestmap小的主机访问失败。并且,我在办公网找了两台机器可100%重现这个问题。

解决:

# echo "0" > /proc/sys/net/ipv4/tcp_tw_recycle

四,扩展

1,net.ipv4.tcp_timestamps

tcp_timestamps的本质是记录数据包的发送时间。基本的步骤如下:

发送方在发送数据时,将一个timestamp(表示发送时间)放在包里面

接收方在收到数据包后,在对应的ACK包中将收到的timestamp返回给发送方(echo back)

发送发收到ACK包后,用当前时刻now - ACK包中的timestamp就能得到准确的RTT

当然实际运用中要考虑到RTT的波动,因此有了后续的(Round-Trip Time Measurement)RTTM机制。

TCP Timestamps Option (TSopt)具体设计如下

Kind: 8 // 标记唯一的选项类型,比如window scale是3
Length: 10 bytes // 标记Timestamps选项的字节数
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| Kind=8 | Length=10 | TS Value (TSval) | TS ECho Reply (TSecr) |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 1 4 4
timestamps一个双向的选项,当一方不开启时,两方都将停用timestamps。比如client端发送的SYN包中带有timestamp选项,但server端并没有开启该选项。则回复的SYN-ACK将不带timestamp选项,同时client后续回复的ACK也不会带有timestamp选项。当然,如果client发送的SYN包中就不带timestamp,双向都将停用timestamp。

tcp数据包中timestamps的value是系统开机时间到现在时间的(毫秒级)时间戳。

参数:

0:停用

1:启用(系统默认值)

2,net.ipv4.tcp_tw_recycle

TCP规范中规定的处于TIME_WAIT的TCP连接必须等待2MSL时间。但在linux中,如果开启了tcp_tw_recycle,TIME_WAIT的TCP连接就不会等待2MSL时间(而是rto或者60s),从而达到快速重用(回收)处于TIME_WAIT状态的tcp连接的目的。这就可能导致连接收到之前连接的数据。为此,linux在打开tcp_tw_recycle的情况下,会记录下TIME_WAIT连接的对端(peer)信息,包括IP地址、时间戳等。这样,当内核收到同一个IP的SYN包时,就会去比较时间戳,检查SYN包的时间戳是否滞后,如果滞后,就将其丢掉(认为是旧连接的数据)。这在绝大部分情况下是没有问题的,但是对于我们实际的client-server的服务,访问我们服务的用户一般都位于NAT之后,如果NAT之后有多个用户访问同一个服务,就有可能因为时间戳滞后的连接被丢掉。

参数:

0:停用(系统默认值)

1:启用

参考:

https://serverfault.com/questions/235965/why-would-a-server-not-send-a-syn-ack-packet-in-response-to-a-syn-packet

http://hustcat.github.io/tcp_tw_recycle-and-tcp_timestamp/

原文地址:https://blog.51cto.com/leejia/1954628

# 配置记录
[root@sz_cc_cbs_download01:~]# cat /etc/sysctl.conf
# Kernel sysctl configuration file for Red Hat Linux
#
# For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and
# sysctl.conf(5) for more details.

# Controls IP packet forwarding
net.ipv4.ip_forward = 0

# Controls source route verification
net.ipv4.conf.default.rp_filter = 1

# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0

# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0

# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1

# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1

# Disable netfilter on bridges.
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

# Controls the maximum size of a message, in bytes
kernel.msgmnb = 65536

# Controls the default maxmimum size of a mesage queue
kernel.msgmax = 65536

# Controls the maximum shared segment size, in bytes
kernel.shmmax = 68719476736

# Controls the maximum number of shared memory segments, in pages
kernel.shmall = 4294967296

net.core.netdev_max_backlog = 32768
net.core.somaxconn = 32768
net.core.rmem_max = 16777216
net.core.rmem_default = 8388608
net.core.wmem_max = 16777216
net.core.wmem_default = 8388608

net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 8192 436600 873200
net.ipv4.tcp_wmem = 8192 436600 873200
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_max_orphans = 3276800
#net.ipv4.tcp_max_orphans = 32768

net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10

net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15

net.ipv4.ip_local_port_range = 1024 65500
net.ipv4.tcp_max_syn_backlog = 16384
#net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_max_tw_buckets = 18000

net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 3
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_abort_on_overflow = 1

net.netfilter.nf_conntrack_max = 65530
net.nf_conntrack_max = 655300
net.netfilter.nf_conntrack_tcp_timeout_established = 1200

vm.swappiness= 5

#########

tcp_tw_recycle和tcp_timestamps     注意:VPC 中,这二个参数只能打开一个,即这两个参数的值一般只能tcp_timestamps  设置为1

linux系统telnet端口不通能收到SYN但不回SYN+ACK响应问题排查(转载)的更多相关文章

  1. Linux 系统Telnet服务

    Linux 系统Telnet服务 telnet与ssh相比,安全性能并不高,但是在ssh版本升级或者其他的情况下还是需要开启这一项服务.linux提供服务是由运行在后台的守护进程daemon来执行的, ...

  2. 大神教你如何解决Linux系统80端口被占用

    有Linux在centos下面安装webmail服务遇到80端口被占用的问题,导致无法继续安装,下面详细介绍下Linux如何查看.查找.关闭监听80端口服务以更好的的解决80端口被占用的问题. 一.查 ...

  3. 解决Linux系统80端口被占用的问题

    有Linux在centos下面安装webmail服务遇到80端口被占用的问题,导致无法继续安装,下面详细介绍下Linux如何查看.查找.关闭监听80端口服务以更好的的解决80端口被占用的问题. 一.查 ...

  4. Linux系统根据端口号来查看其进程并杀死进程

    1.首先是查看某个端口号,(以httpd服务为例) 2.查看此端口下进程以及进程号 3.我们使用awk命令过滤出第二列,即进程号 4.杀死进程 报错的这一行表示,要杀死的进程PID为3754,但是没有 ...

  5. Redis linux 外部telnet访问不通

    外部访问不通: 1.修改redis.conf中的daemonize的值设为no: 2.修改redis.conf中的bind的值127.0.0.1为linux本身的ip地址,如192.168.1.120

  6. Linux系统443端口被占用无法启动解决办法

    etstat -ano|findstr "443"         //搜索443端口占用情况,并找到进程IDTCP 0.0.0.0:443 0.0.0.0:0 LISTENING ...

  7. 类linux 系统上端口被占用

    好几次遇到这问题,明明Ctrl+C退出了node,但是下次启动的时候总是会报错: listen EADDRINUSE :::80 之类的. 这时候可能是被占用,也可能是上次进程没有真的退出. ps - ...

  8. Linux 系统开启随机端口数量 调优

    Linux系统随机端口 默认Linux系统开启的随机端口范围为 32768 ~ 65535.客户端连接服务监听端口需要使用到随机端口连接. Linux系统随机端口调优 1.添加内核配置参数:/etc/ ...

  9. Linux系统安装后IP能通端口不通的问题处理方法

    网上大部分都是针对防火墙的问题,这里首先排除防火防火墙导致端口不通的问题! 1.排除防火墙问题(防火墙的排查方式网上一搜全是,这里不再赘述) 2.查看检查端口有没有监听,发现端口未监听(比如8080端 ...

随机推荐

  1. Andrew Ng机器学习 二: Logistic Regression

    一:逻辑回归(Logistic Regression) 背景:假设你是一所大学招生办的领导,你依据学生的成绩,给与他入学的资格.现在有这样一组以前的数据集ex2data1.txt,第一列表示第一次测验 ...

  2. 完成N!的程序编写: 1、用循环算法编写; 2、用递归算法编写;

    完成N!的程序编写 1.用循环算法编写 #include<iostream> using namespace std; int main(){ int n; long result = 1 ...

  3. 堆(python)

    # -*- coding:utf-8 -*- class Array(object): def __init__(self, size=32): self._size = size self._ite ...

  4. synchronized(修饰方法和代码块)

    synchronized(修饰方法和代码块) 1. 含义 synchronized 是同步锁,用来实现互斥同步. 在 Java 中,关键字 synchronized 可以保证在同一个时刻,只有一个线程 ...

  5. LightOJ - 1299 - Fantasy Cricket(DP, 数学)

    链接: https://vjudge.net/problem/LightOJ-1299 题意: 考虑成,U位置的点要往后放,D位置往前放 Dp[i][j]表示处于i位置,还有j个U没有放下. s[i] ...

  6. PAT乙级1045 快速排序

    1045 快速排序 (25分)   著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边. 给定划分后的 ...

  7. javaweb学习笔记(三)

    一.javaweb高级(Filter和Listener)的简单介绍 1.过滤器Filter (https://www.cnblogs.com/vanl/p/5742501.html) ①定义 Filt ...

  8. Greenplum 添加mirror步骤

    原文链接:https://yq.aliyun.com/articles/695864 [TOC] 概述 新安装的greenplum集群只有primary节点,没有mirror.高可用性没得到保证.所以 ...

  9. jsp+ tinymce粘贴word

    最近公司做项目需要实现一个功能,在网页富文本编辑器中实现粘贴Word图文的功能. 我们在网站中使用的Web编辑器比较多,都是根据用户需求来选择的.目前还没有固定哪一个编辑器 有时候用的是UEditor ...

  10. piplinedb 团队加入confluen

    这个消息对于使用pipelinedb 的人来说,可能有点不好,因为官方已经明确说明了,pipelinedb 截止到1.0 版本,将不再维护了, 基本就要靠社区了,但是pipelinedb 团队还是比较 ...