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. [LeetCode] 0279. Perfect Squares 完全平方数

    题目 Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9 ...

  2. mysql in条件查询到底会不会用到索引

    MySQL 的 in 查询在 5.5 以上的版本中存储引擎都是 innodb 的,正常情况下会走索引的!至于 MyISAM 没试过! 如果是 5.5 之前的版本确实不会走索引的,在 5.5 之后的版本 ...

  3. 1210 BBS admin后台管理及侧边栏筛选个人站点

    目录 昨日内容 django admin后台管理 使用 建表 用户图片的显示 MEDIA用户配置 查找照片 搭建个人站点 防盗链 新建css文件 侧边栏展示标签 定义分类栏与标签栏 定义时间栏 侧边栏 ...

  4. 行为型模式(十) 备忘录模式(Memento)

    一.动机(Motivate) 我们看上图,一个对象肯定会有很多状态,这些状态肯定会相互转变而促进对象的发展,如果要想在某一时刻把当前对象回复到以前某一时刻的状态,这个情况用"备忘录模式&qu ...

  5. Spring源码窥探之:xxxAware接口

    Aware接口是一个标志性接口,继承此接口的接口xxxAware的实现类,在容器创建完成后,会回调实现方法,下面举例: 1. 有很多xxxAware接口,下面举两个例子 /** * descripti ...

  6. drf框架 - 请求模块 | 渲染模块

    Postman接口工具 官方 https://www.getpostman.com/ get请求,携带参数采用Params​post等请求,提交数据包可以采用三种方式:form-date.urlenc ...

  7. JanusGraph 创建索引步骤(composite index)踩坑总结

    前言 JanusGraph是一个图数据库引擎,安装及入门可以参考 JanusGraph 图数据库安装小记.为了提高查询速度,在使用过程中一般要为某些属性创建索引.这篇随笔主要是记录创建索引过程中踩过的 ...

  8. 洛谷 P1140 相似基因 题解

    每日一题 day23 打卡 Analysis dp[i][j]表示序列A中前i个与序列B中前j个匹配的相似度最大值 所以,dp方程很容易想到: 1.让a[i]与b[j]匹配 2.让a[i]与B序列中一 ...

  9. fedora安装设置

    添加视频解码rpmfusion源: sudo rpm -ivh http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-st ...

  10. npm 更新包

    方法一手动跟新: 手动修改package.json中依赖包版本,执行npm install --force,强制从远程下载所有包更新本地包 方法二使用第三方插件: npm install -g npm ...