TCP/IP

TCP 三次握手

image-center

系统设置

配置主机名

$ sudo nmcli general hostname hollyshit
$ sudo hostnamectl set-hostname hollyshit

配置 IP 地址

$ sudo vi /etc/sysconfig/network-scripts/ifcfg-ens33
IPADD=192.168.1.10
DNS=192.168.1.5
GATEWAY=192.168.1.1
NETMASK=255.255.255.0
ZONE=public
ONBOOT=yes
$ sudo systemctl restart network

修改 http 的最大并发请求数

查看当前最大并发数的配置

$ ulimit -n
1024

修改 /etc/security/limits.conf

* soft nofile 10240
* hard nofile 10240
neo hard nofile 10240

第一列可以指定用户或组,也可使用 *% 通配符。指定组时,组名前面加 @,如 @admin。修改后需 重启 系统才能生效。

* 代表作用于所有用户,第三行的 neo 是指定用户名。

hard 限定的值只能由管理员配置,对于用户来说,该值是上限,不可逾越。

soft 所限定的值用户自己可以用 ulimit -S -n 1024 调整,但不可超过 hard 值。

nofile :Number of Open file descriptors,即文件描述符总数的上限。

路由设置

使用 route 来查看和管理 IP 路由表。

添加主机路由

$ route add -host 192.168.197.100 dev etho

添加默认网关

$ route add default gw 192.168.197.1

添加网络路由

$ route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
$ route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.197.1

网络监控

查看 http 并发请求数以及 TCP 连接状态

$ ss -s

Total: 593
TCP:   6 (estab 1, closed 1, orphaned 0, timewait 0)

Transport Total     IP        IPv6
RAW      1         0         1        
UDP      8         4         4        
TCP      5         3         2        
INET      14        7         7        
FRAG      0         0         0
#或

$ netstat -n | awk '/^tcp/{a[$NF]++} END{for(i in a){print i,a[i]}}'
ESTABLISHED 12

查看哪个地址对 80 端口的访问次数最多

tcpdump 嗅探 80 端口的访问,看谁最高。

$ sudo tcpdump -i venet0 -tnn dst port 80 -c 1000 \
| awk '/^IP/{print $2}' \
| awk -F. '{print $1 "." $2 "." $3 "." $4}' \
| uniq -c \
| sort -rn

使用 tcpdump 监听 “目标主机为 192.168.1.1,目标端口为 tcp/80” 的数据,同时将输出结果保存到 tcpdump.log

$ sudo tcpdump -i ens33 'host 192.168.1.1 and port 80' > tcpdump.log

用 tcpdump 嗅探对本地 80 端口的访问流量,列出访问量最大的 IP 地址

$ sudo tcpdump -i ens33 -tnn dst port 80 -c 1000 \
| awk '/^IP/{print $2}' \
| awk -F. '{print $1 "." $2 "." $3 "." $4}' \
| uniq -c | sort -rn

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
20 packets captured
21 packets received by filter
0 packets dropped by kernel
      24 192.168.1.19
      2 192.168.1.16

-i :指定监听的网卡

-t :不显示每行的时间戳

-n :不转换地址,如把 IP 地址转换为主机名,把端口号转换为服务名

-nn :不转换协议和端口号,不把地址转换为主机名

-c :count,抓包数量

查看连接到本机的每个 IP 的连接数量

先看一下 netstat -n 的查询结果:

netstat -n
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0    304 192.168.1.9:22          192.168.1.6:14148       ESTABLISHED
udp      832      0 192.168.1.9:51696       192.168.1.5:53          ESTABLISHED
udp6       0      0 fe80::d558:6d:c1d:51207 fe80::1:53              ESTABLISHED
Active UNIX domain sockets (w/o servers)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  3      [ ]         DGRAM                    15623    /run/systemd/notify
unix  20     [ ]         DGRAM                    15634    /run/systemd/journal/dev-log
unix  8      [ ]         DGRAM                    15642    /run/systemd/journal/socket

我们只需要取 tcp 开头的行,第 5 列的值,如 192.168.1.6:14148,把 端口号 去掉,统计 总数。

$ netstat -n \
| awk '/^tcp/{print $5}' \
| awk -F: '{print $1}' \
| sort \
| uniq -c \
| sort -rn

IPTABLES

端口转发

将对本地 80 端口的请求转发到本地 8080 端口,IP 地址为 10.0.0.254。

$ sudo iptables -A PREROUTING \
 -t nat \
 -p tcp -d 10.0.0.254 --dport 80 \
 -j DNAT --to-destination 10.0.0.254:8080

查看当前 NAT 规则

$ sudo iptables -t nat -L -n -v
Chain PREROUTING (policy ACCEPT 217 packets, 37261 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    3   156 DNAT       tcp  --  *      *       0.0.0.0/0            192.168.1.21         tcp dpt:80 to:192.168.1.21:8080

-t:指定表

-L:列出规则

-n:不显示主机名,而显示 IP 地址

-v:显示更详细的信息

删除特定规则

先用 -L --line-numbers 参数来显示行号,然后通过指定行号来删除规则。

删除 filter 表中的规则

$ sudo iptables -L -n --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination         
1    ACCEPT     tcp  --  0.0.0.0/0            192.168.1.21         tcp dpt:80

因为 filter 是默认的表,因此无需显式指定表,只需指定要删除的规则所在的 及规则的 行号

$ sudo iptables -D INPUT 1

删除 nat 表中的规则

列表时必须 显式指定 nat 表:

$ sudo iptables -t nat -L -n --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    DNAT       tcp  --  0.0.0.0/0            192.168.1.21         tcp dpt:80 to:192.168.1.21:8080

同样地,删除时也要显式指定 nat 表,然后指定 PREROUTING 链以及规则所在行号:

$ sudo iptables -t nat -D PREROUTING 1

禁止特定 IP 地址访问

iptables -A INPUT -s 192.168.1.55 -j REJECT

日志报错

症状:

服务器负载正常,但请求大量超时,服务器/应用访问日志看不到相关请求记录。

在 dmesg 或 /var/log/messages 看到大量以下记录:

kernel: nf_conntrack: table full, dropping packet.

原因:

服务器访问量大,内核 netfilter 模块 conntrack 相关参数配置不合理,散列表被填满,导致 IP 数据包被丢弃,连接无法建立。

解决:

  • 关闭防火墙
  • 将散列表扩容
  • 修改规则,禁用一些不必要的追踪

查看连接追踪表信息

查看追踪表中所有条目:

$ sudo cat /proc/net/nf_conntrack
ipv4     2 tcp      6 299 ESTABLISHED src=192.168.1.6 dst=192.168.1.77 sport=11385 dport=22 src=192.168.1.77 dst=192.168.1.6 sport=22 dport=11385 [ASSURED] mark=0 secctx=system_u:object_r:unlabeled_t:s0 zone=0 use=2
ipv4     2 tcp      6 60 SYN_SENT src=192.168.1.77 dst=192.168.1.78 sport=60638 dport=3306 [UNREPLIED] src=192.168.1.78 dst=192.168.1.77 sport=3306 dport=60638 mark=0 secctx=system_u:object_r:unlabeled_t:s0 zone=0 use=2

查看条目总量上限:

$ sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 31248

$ cat /proc/sys/net/netfilter/nf_conntrack_max
31248

查看当前已有条目:

$ sysctl net.netfilter.nf_conntrack_count
net.netfilter.nf_conntrack_count = 3

$ cat /proc/sys/net/netfilter/nf_conntrack_count
3

查看追踪表大小:

$ sysctl net.netfilter.nf_conntrack_buckets
net.netfilter.nf_conntrack_buckets = 8192

$ cat /proc/sys/net/netfilter/nf_conntrack_buckets
8192

计算负载系数:

Load Factor = nf_conntrack_count / nf_conntrack_buckets

如果负载系数超过 0.67 就要考虑扩容追踪表了。

FirewallD

添加端口

$ sudo firewall-cmd --permanent --add-service=http

DNS

DNS 的查询顺序

  1. 本地 hosts 文件
  2. 本地 DNS 缓存
  3. 本地 DNS 服务器
  4. 发起迭代查询

DNS 的组成

  • 域名服务器:提供域名解析的软件,默认监听 udp/tcp 53 端口
  • 解析器:访问域名服务器的客户端,获取域名服务器的响应以后,它负责解析出结果,将结果返回给调用者

域名服务器的分类

权威域名服务器

负责授权域下的域名解析服务,由上级权威域名服务器使用 NS 记录进行授权。

权威 DNS 是特定的域名记录(如 example.com)在域名注册商处所设置的 DNS 服务器,用于特定域名的管理。该服务器只对自己所拥有的域名进行解析,对于其他域名则拒绝访问。

权威 DNS 由 域名解析服务商 建设,提供 域名管理服务,维护域名解析记录。

权威域名服务器有以下三级:

根域名服务器

.root 域名服务器,负责对 .com、 .cn、.org 等顶级域名向下授权。

www.example.com 真正的域名是 www.example.com.root,简写为 www.example.com.。因为,根域名 .root 对于所有域名都是一样的,所以平时是省略的。

顶级域名服务器
  • 通用顶级域名服务器:服务于 .org、.com、.info 等授权的域名服务器
  • 国家代码服务器:服务于 .uk、.cn、.us 等授权的域名服务器
二级域名服务器

服务于具体的域名,如解析 baidu.com 等。

缓存域名服务器

这类的域名服务器负责接受解析器发过来的 DNS 请求,通过依次查询 根域名服务器 -> 顶级域名服务器 -> 二级域名服务器, 来获取 DNS 解析结果,然后把结果发送给解析器。同时,根据 DNS 条目的 TTL(time to live)值进行缓存。

缓存域名服务器的作用:

  • 企业内部局域网自用 DNS 服务
  • 运营商为其租户提供 DNS 服务
  • 开放的 DNS 解析服务,如 OpenDNS

转发域名服务器

这类域名服务器负责把解析器发过来的 DNS 请求,转发给指定的上级域名服务器,以获得 DNS 解析条目,然后把结果发给解析器。和缓存域名服务器不同的是,这类服务器 不进行任何缓存,只是转发而已。

DNS 查询机制

DNS 采用两种查询机制:递归查询迭代查询

image-center

从客户端到本地 DNS 服务器是属于递归查询,而 DNS 服务器之间的交互查询是迭代查询。

递归查询

DNS 服务器接收到客户端请求,必须用一个 准确的查询结果 回复客户机。

如果 DNS 服务器本地没有存储查询 DNS 信息,那么该服务器会询问其他服务器,并将返回的查询结果提交给客户机。

迭代查询

DNS 服务器会向客户端提供能够解析查询请求的 其他 DNS 服务器地址

当客户端发送查询请求时,DNS 服务器并不直接回复查询结果,而是告诉客户端另一台 DNS 服务器的地址,客户端再向这台 DNS 服务器提交请求,依次循环直到返回查询的结果为止。

DNS 使用的端口号

DNS 协议使用 udp/tcp 的 53 端口提供服务。

为什么同时使用两种协议?

  • 客户端向 DNS 服务发起请求时,使用 udp 的 53 端口,因为 速度快
  • DNS 服务器之间进行区域传输时,使用 TCP 的 53端口,因为 传输可靠、可控

智能 DNS 的实现原理

用户发起 DNS 解析请求时,先判断该用户来自于哪个运营商,然后将请求转发给该运营商指定的 IP 地址处理,避免跨运营商访问,提升解析速度。

网络检测

用脚本 ping 多个 IP 地址

连续 IP 地址

连续 ping 某个网段,如 192.168.1.0/24。

#!/bin/bash
for ip in `seq 1 255`
do
  ping -c 1 192.168.1.$ip > /dev/null 2>&1
  if [ $? -eq 0]; then
    echo 192.168.1.$ip is ONLINE
  else
    echo 192.168.1.$ip is OFFLINE
  fi
done
wait

不连续 IP 地址

给定一系列非连续 IP 地址,保存在文本中,每行一个地址:

10.12.13.14
172.15.48.3
192.168.45.54
...
48.114.78.227
#!/bin/bash
cat /path/to/list.txt | while read output
do
  ping -c 1 "$output" > /dev/null
  if [ $? -eq 0 ]; then
    echo "node $output is up"
  else
    echo "node $output is down"
  fi
done