计算机网络常见概念介绍 路由 NAT

路由器

路由器(router)是互联网的枢纽,是连接英特网中各局域网、广域网的设备,它会根据信道的情况自动选择和设定路由,以最佳路径,按前后顺序发送数据。作用在OSI模型的第三层,提供了路由与转发两种重要机制。

路由器就是完成路由过程的设备,从构成上看,它是一个完整的计算机系统,包括硬件,操作系统和应用软件算法,与通用计算机系统的不同之处就在于,路由器硬件以通讯处理为主要设计目标,特别是 I/O部分。

  • 那么路由器是如何进行包的转发的呢?就像一个人如果在去某个地方,一定要在他的脑海里有一张地图,在每个路由器的内部也有一张地图,这张地图就是路由表
  • 在这个路由表中包含有该路由器掌握的所有目地网络地址,以及通过此路由器到达这些网络中最佳路径,这个最佳路径指的是路由器的某个接口或下一条路由器的地址
  • 这是由于路由表的存在,路由器才可以依据路由表进行包的转发,把数据包转发到路由器的指定网口
  • 路由器是一种具有多个输入端口和多个输出端口的专用计算机,其任务是转发分组,也就是说,将路由器某个输入端口收到的分组,按照分组要去的目的地,把该分组从路由器的某个合适的输出端口转发给下一跳的路由器。下一跳的路由器也按照这种方法处理分组,直到该分组到达终点为止

①一个帧到达路由器后,首先检查帧中目标MAC地址是否是本接口的MAC,如不是则丢弃,如是则解封装并将IP包移动到路由器内部。②将IP包中目标IP与路由表进行匹配,如匹配路由表不成功,则丢弃,返回ICMP错误消息;若成功,则将数据路由到相应的出口,再封装帧头帧尾。③检查ARP缓存中是否有下一跳的MAC,如有则重新封装出去;如没有,则发送ARP请求广播报文获取下一跳的MAC,并记录到ARP缓存表中,再重新封装数据帧发送出去。

路由器功能

  • 路由:收集网络拓扑信息并动态形成路由表
  • 转发:根据转发表(FIB)转发IP数据包
  • 子网间速率适配
  • 隔离子网
  • 隔离广播域
  • 指定访问规则
  • 不同类型的网络互联:路由器经常会收到以某种类型的数据链路帧封装的数据包,当转发这种数据包时,路由器可能需要将其封装为另一种类型的数据链路帧。数据链路封装取决于路由器接口的类型及其连接的介质类型

路由表

  • 路由表是在路由器中维护的路由条目的集合,路由表为路由做出最佳路径选择提供依据
  • 需要通过静态路由或者动态路由添加路由规则到路由器

实际中由于路由器开发厂商的不同,路由表中的信息也不尽相同,但是几乎都包含五项基本信息:

  • 目标网络的IP地址:32位,这里在上文提到,是目标网络的IP地址而非目标计算机的IP地址
  • 目标网络的子网掩码:32位,即子网掩码,没什么好解释
  • 下一跳IP地址:32位,如果目标网络需经过多个路由器,下一跳即使下一个路由器的IP地址
  • 出接口名字:路由器会提供多个接口,每个接口通向不同的网段,所以表项中需要提供该项,即使确定IP分组从哪一个接口发出去,出接口只是标识本路由器的信息
  • 度量:从该路由器到达目标网络的代价,这个属性反映这一路径的优劣,由于路由协议的不同,该项具体数据形式也不同,常见的有跳数(途径路由器的数量),当前往返时间,最窄链路带宽等等

路由表简单示例:

IP或网段 mask 接口 距离 下一跳IP
1.0 255.255.255.0 E0 1 173…
2.0 255.255.255.0 S0 2 173…

注意:
数据包经过路由器,源IP与目标IP是不改变的,除非做了NAT。不过mac地址是变化的,因为发送端开始不知道目的主机的mac地址,所以每经过一个路由器mac地址是变化的。MAC通过ARP协议获得

NAT

NAT英文全称是“Network Address Translation”,中文意思是“网络地址转换”。NAT 功能通常被集成到路由器、防火墙、ISDN路由器或者单独的NAT设备中。

分类

NAT有三种类型:静态NAT(Static NAT)、动态地址NAT(Pooled NAT)、网络地址端口转换NAPT(Port-Level NAT)

静态NAT

通过手动设置,使 Internet 客户进行的通信能够映射到某个特定的私有网络地址和端口.在静态NAT方式中,内部的IP地址与公有IP地址是一种一一对应的映射关系,所以,采用这种方式的前提是,机构能够申请到足够多的全局IP地址

动态NAT

当数据包进出内网时,具有NAT功能的设备对IP数据包的处理与静态NAT的一样,只是NAT table表中的记录是动态的,若内网主机在一定时间内没有和外部网络通信,有关它的IP地址映射关系将会被删除,并且会把该全局IP地址分配给新的IP数据包使用,形成新的NAT table映射记录

网络地址端口转换NAPT

网络地址端口转换NAPT(Network Address Port Translation)则是把内部地址映射到外部网络的一个IP地址的不同端口上。

有两种类型:

  • 源NAT(Source NAT,SNAT):修改数据包的源地址
  • 目的NAT(Destination NAT,DNAT):修改数据包的目的地址

NAT原理

  • 地址转换
  • 连接跟踪,通过TrackTable
  • 端口转换,通过TrackTable

主要应用

  • 数据包伪装
  • 端口转发
  • 负载均衡

缺陷

  • 不能处理嵌入IP地址端口
  • 有一些应用程序A端口是命令端口,B端口是数据端口,NAT不知道B要映射B端口
  • P2P,需要P2P NAT穿透技术

网络图

NAT网络图

序列图

NAT序列图

扩展

反向链接

有Client与Server两台服务器,Client服务器同时启动一个服务端程序,客户端发送IP端口信息通知Server我启动了一个服务端程序你可以连接过来发送消息,这种一般要同网段才能使用,不同网段需要做路由转发一般都是只做Client到Server的路由转发,这样反过来(Server→Client)也得做一套而且Client可能非常多需要配置的转发会非常多。

7547端口被IANA分配用于CPE广域网控制协议,CPE可以在该端口监听接收请求,收到请求就连接网管URL。反向链接使用,就是网管连接基站7547端口,基站断开连接,主动通过TR069与网管通过inform建立链接。 ConnectionRequestURL 参数指定CPE本机ACS URL

利用UDP打洞

TCP和UDP在打洞上却有点不同。这是因为伯克利socket(标准socket规范)的API造成的。UDP的socket允许多个socket绑定到同一个本地端口,而TCP的socket则不允许。
利用UDP打洞后,客户端与服务端可以使用短连接。当服务端需要与客户端进行通信的时候,通过UDP通知客户端通过TCP连接服务端,连接上服务端后服务端就可以通过TCP下发信息给客户端了。

在TR069协议中应用:CPE定时发送请求保持STUN NAT绑定,STUN的绑定让CPE与STUN服务器存在一条网络链路,ACS然后发送UDP connection Request(走UDP协议,应用层协议用HTTP1.1)源IP端口使用STUN服务器的IP地址,发送到STUN服务器关联的CPE设备,进而CPE发起tr069规范中定义的6 connection request事件(TCP连接成功)。具体详细描述在TR111协议中也包含在TR069协议的附录中了,协议中具体描述了整个流程,比如通过比较MAPPED-ADDRESS判断CPE与STUN服务器之间是否经过NAT转换等。(消息可以通过打洞后通过STUNServer进行转发,也可以通过打洞后通过NAT网关直接转发)

UDP打洞过程:

  1. 双方都通过UDP与服务器通讯后,网关默认就是做了一个外网IP和端口号 与你内网IP与端口号的映射,这个无需设置的,服务器也不需要知道客户的真正内网IP
  2. 用户A先通过服务器知道用户B的外网地址与端口
  3. 用户A向用户B的外网地址与端口发送消息,
  4. 在这一次发送中,用户B的网关会拒收这条消息,因为它的映射中并没有这条规则。
  5. 但是用户A的网关就会增加了一条允许规则,允许接收从B发送过来的消息
  6. 服务器要求用户B发送一个消息到用户A的外网IP与端口号
  7. 用户B发送一条消息,这时用户A就可以接收到B的消息,而且网关B也增加了允许规则
  8. 之后,由于网关A与网关B都增加了允许规则,所以A与B都可以向对方的外网IP和端口号发送消息。

跳板机外网ssh到内网服务器

在授权的IP服务器上搭建VPN作为跳板是一种解决方案。

机器上执行命令,建立SSH反向隧道。

不要在linux上启用net.ipv4.tcp_tw_recycle参数

net.ipv4.tcp_tw_recycle 这个参数是默认关闭的,打开这个参数开启后,可以使TCP连接中TIME-WAIT sockets的快速回收,但是在NAT网络下,导致大量的TCP连接建立错误、所以在公司内部有时候能访问,有时候访问不上。这个参数会对同一个请求 IP 按照时间戳增续处理, 凡是小于上次时间戳的链接请求, 都被认为是重传包而丢弃.

原来是 net.ipv4.tcp_timestamps 设置了为 1 ,即启用时间戳,经过nat之后,如果前面相同的端口被使用过,且时间戳大于这个链接发出的syn中的时间戳,服务器上就会忽略掉这个syn,不返会syn-ack消息,表现为用户无法正常完成tcp3次握手,从而不能打开web页面。在业务闲时,如果用户nat的端口没有被使用过时,就可以正常打开;业务忙时,nat端口重复使用的频率高,很难分到没有被使用的端口,从而产生这种问题。

1
2
netstat -s | grep timestamp # 查看拒绝连接的情况
# 可以看到大量请求由于timestamp被拒绝

先确定参数:

1
2
cat /proc/sys/net/ipv4/tcp_tw_recycle
cat /proc/sys/net/ipv4/tcp_timestamps

在/etc/sysctl.conf配置文件添加如下内容:

1
2
net.ipv4.tcp_tw_recycle = 0 # 开启过,后续必须在这边加上相关配置才能关闭
net.ipv4.tcp_timestamps = 0

执行如下命令,使配置生效:

1
2
3
4
5
sysctl -p

# 解决:error: "net.bridge.bridge-nf-call-ip6tables" is an unknown key
modprobe bridge
lsmod|grep bridge

同时开启timestamp(时间戳)和tw_recycle(快速回收),会导致在一个MSL时间内只响应timestamp递增的请求,对于时间戳较小的请求都抛弃了(不响应ack)。

MSL扩展: RFC793中规定MSL为2分钟,也就是说2分钟内同一个ip的请求的时间戳要求递增,不是递增的话服务器不予响应。

其他导致服务器丢包的原因与排查

防火墙策略

1
2
# 查看防火墙策略
iptables-save -t filter

连接跟踪表溢出

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
# 查看nf_conntrack表最大连接数
$ cat /proc/sys/net/netfilter/nf_conntrack_max
65536
# 查看nf_conntrack表当前连接数
$ cat /proc/sys/net/netfilter/nf_conntrack_count
123
# 如果输出值中有“nf_conntrack: table full, dropping packet”,说明服务器nf_conntrack表已经被打满
dmesg |grep nf_conntrack


# 设置参数
sysctl -w net.netfilter.nf_conntrack_max=524288
sysctl -w net.nf_conntrack_max=524288
sysctl -w net.netfilter.nf_conntrack_buckets=121344 #如果报错可以改用这个命令: echo 121344 > /sys/module/nf_conntrack/parameters/hashsize
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600

# 执行dmesg |grep nf_conntrack
# 如果出现 nf_conntrack: falling back to vmalloc. 说明nf_conntrack buckets设置过大,按半数减小,进行测试。 查看是否还报错/var/log/messages
sysctl -w net.netfilter.nf_conntrack_max=131072
echo 32768 > /sys/module/nf_conntrack/parameters/hashsize
# 防止重启系统后配置失效。
echo "echo 32768 > /sys/module/nf_conntrack/parameters/hashsize" >> /etc/rc.local
# 或者
vi /etc/sysctl.conf # 添加 net.netfilter.nf_conntrack_buckets = 32768
# sysctl -p

还可以考虑关闭跟踪

Ring Buffer溢出

netdev_max_backlog溢出

反向路由过滤

半连接队列溢出

PAWS Protect Againest Wrapped Sequence numbers

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
# 查看相关网络统计
ss - int
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉

#对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于255,默认值是5,对应于180秒左右时间
net.ipv4.tcp_syn_retries=2
#net.ipv4.tcp_synack_retries=2
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout = 30 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
net.ipv4.tcp_keepalive_time = 1200 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.ip_local_port_range = 1024 65000 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.tcp_max_syn_backlog = 8192 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_tw_buckets = 5000 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。
默 认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。

参数调整太多可能还要重启下应用程序才能保证正常运行

仪器协议

一般仪器使用:SCPI应用层协议也就是简单字符串的收发,下层协议是可以根据具体情况替换的。

仪器可以支持的I/O:

  1. Single-session: GPIB、USB-488、LAN VXI-11(SICL)
  2. Multi-Session: LAN Socket、LAN HiSLIP、LAN Telnet
1
2
3
4
5
6
7
Application > SCPI
Presentation > XDR(VXI-11)
Session > ONC-RPC ----这个以及以上在TCP/IP分层中都可以算是应用层协议
Transport > TCP/UDP
Network > IP
DataLink > Ethernet/802.3
Physical > 802.3/10BASE-

ONC-RPC(Open Network Computing Remote Procedure Call) 默认端口111

其他概念说明

您可​以​使​用​GPIB​(IEEE 488)、​串​口​(RS232、​RS485(两根线,TR)​和​RS422)​或​以​太​网​接​口​
GPIB是General Purpose Interface Bus缩写
一般内部网络都可以通过路由器双向互通,只有少数经过NAT的网络可能只能单向主动发起连接然后才能双向互相通信。

参考