懒猫微服实战入门(三十四):方寸之间,自有天地:懒猫微服,男人的网络瑞士军刀

忘机山人

发布于118天前
博客图片修整中,看不了可以先搜索公众号“忘机山人”看。
曾几何时,中文互联网圈流行着这样一个段子,叫做中年男人三件套:NAS、软路由、充电头。

我们今天就来聊聊第一个。NAS 似乎是给职业运维人员的福音,而广大的爱好者们通常都是野路子,靠着一腔孤勇或者是兴趣来维护自己的小小世界,能够借鉴参考的,也就是互联网的帖子以及各种群里的答疑而已。

靠着坚持不懈,入门了 Linux 和网络,但是不求甚解,安静的文件存储,只躺在方寸之间。


https://appstore.lazycat.cloud/#/shop/detail/cloud.lazycat.app.ubuntu



如果你恰好有一台懒猫微服,那么我们正好可以一起来学习这繁杂的网络,拆解这美丽的网络新世界。

我从事过几年的云行业,在发烧友和职业人员之间横跳,于是心有所感,立志让爱好者可以有专业的技术,让职业人员可以真的产生兴趣。这是网络篇。

首先你一定听说过 IP 地址,这是互联网通信的门牌号。我们的手机、电脑,包括懒猫微服都有一个 IP 地址。当你连上网络的时候,这个地址就被分配给了设备。准确地说,是分配给了网卡,所以懒猫微服可以用转接口来拓展第二张网卡。

连上网线之后,第一步我们习惯在路由器上看 IP 地址,然后 ping 一下确认连通。懒猫微服使用 IPv6,可以用 `ping -6` 或 `ping6`。

### 循迹(ping、telnet)

```bash
ping 192.168.x.x
# 如果是 IPv6
ping -6 xxx.heiyu.space
# 或者
ping6 xxx.heiyu.space
```

我们也可以用 dig 查看域名解析的 IP 地址:

```bash
dig +short xxx.heiyu.space # 因为是 IPv6,没有 IPv4 所以解析不到
dig AAAA +short xxx.heiyu.space  # 查 IPv6
dig @8.8.8.8 xxx.heiyu.space AAAA +short # 指定 DNS 服务器查询,也是可以查询到的
nslookup xxx.heiyu.space  # Windows 可以使用这个
```
在登录之前,可以用 telnet 看端口连通性,然后 SSH 上去。不过一般来说,直接 `ssh root@域名/地址` 就可以登录了。

```
telnet xxx.heiyu.space 22
```

登录之后,我们可以使用 ifconfig 来看网卡信息。主要有这几张网卡比较有用:


- enp2s0	物理网卡,连接家里路由器
- wlp129s0	无线网卡
- lo	回环接口,本机访问本机用(127.0.0.1)
- heiyu-0	懒猫穿透隧道,IPv6 内网穿透用
- docker0	Playground Docker 默认网桥

或者使用 `ip addr`,会更加现代一点。
```
 lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute
       valid_lft forever preferred_lft forever

2: enp2s0:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether xxxxxx brd ff:ff:ff:ff:ff:ff
    altname enx500a52087489
    inet 192.168.8.145/24 brd 192.168.8.255 scope global dynamic noprefixroute enp2s0
       valid_lft 27083sec preferred_lft 27083sec
    inet6 fe80::b7ea:8784:599d:506e/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
```


我们再来看一下路由表,使用 `route -n` 或者 `ip route` 来查看:

```
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.8.1     0.0.0.0         UG    100    0        0 enp2s0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-0da48190134d
......
172.100.0.0     0.0.0.0         255.255.255.0   U     0      0        0 docker0
192.168.8.0     0.0.0.0         255.255.255.0   U     100    0        0 enp2s0
```

路由表决定了数据包往哪里走。

第一条 `0.0.0.0/0` 是默认路由,所有未知目的地的数据包都会被转发到网关 192.168.8.1(你的路由器)。路由器会通过 NAPT 来实现多台设备共用一个公网 IP 访问互联网。最后一条 `192.168.8.0/24` 是局域网直连,不需要经过网关。`172.100.0.0/24` 是 Docker 网桥。

> NAPT(Network Address Port Translation)是 NAT 的一种,
> 也叫 PAT(Port Address Translation),它允许多个内部主机共享一个公网 IP 地址,
> 通过不同的端口号来区分不同的连接。
> 你家路由器做的其实是 NAPT:
>
> 192.168.1.100:12345 → 公网IP:50001
> 192.168.1.101:12345 → 公网IP:50002
> 192.168.1.102:12345 → 公网IP:50003

如果你家里恰好有公网 IP,那么也可以通过在路由器上配置端口映射,将外部端口映射到内部的 IP 地址和端口上,让 NAS 可以被外网访问。

比如,你想让 NAS 的 SSH 服务(默认端口 22)可以从外网访问,可以在路由器上配置端口映射,将路由器的端口(比如 2222)映射到 NAS 的 IP 地址(比如 192.168.1.100)的 22 端口上。

不过懒猫微服自带了内网穿透,我们可以不用折腾这个部分了。

一般来说,家庭路由器的 IP 是 192.168.X.1,所以我们的机器可能是 192.168.X.2 或者其它地址。也就是说 192.168.X.0/24 就是我们局域网的网段。

> 192.168开头的是C类IP地址,后面/24表示子网掩码,也就是255.255.255.0
> 二进制表示就是 11111111.11111111.11111111.00000000
> 
> 也就是前24位是网络号,后8位是主机号。
> 
> 一个子网内,主机号不能全为0或者全为1
> 
> 192.168.1.0  网络地址(全0)
> 
> 192.168.1.255 广播地址(全1)
> 
> 192.168.1.1-192.168.1.254 可用地址
> 如果你的设备足够多,200 多个可能不太够用,那么就需要用更大的网段,比如 172.16.0.0/12,也就是 172.16.0.0 - 172.31.255.255 可用地址。
> 你也可能看到过 10 开头的地址,这是 A 类私有地址,范围更大:10.0.0.0 - 10.255.255.255。


好了,回到 DNS(Domain Name System)。它是互联网的核心服务之一,作为域名和 IP 地址相互映射的分布式数据库,让我们可以通过域名来访问网站,而不用记一串数字。由于懒猫做了转发,实际看到的不是真正的 IP 地址,这里我们快速略过。

在局域网内也可以用 dig 查看 IPv4 地址:

```bash
dig +short your-lazycat.local
```

这里看到的地址就和路由器上显示的一样了。


如果想要使用IPv6,那么你需要确保你的网络环境支持IPv6,并且你的路由器也支持IPv6。你可以通过以下命令来查看你的IPv6地址:

```bash
ip addr show | grep inet6
```

因为 IPv4 地址已枯竭且存在 NAT 性能损耗,现代互联网依据 RFC 6724 国际标准和 Happy Eyeballs 算法,在操作系统和浏览器底层默认赋予了 IPv6 更高的连接优先级(Precedence),旨在确保连接更直接、高效的同时,通过给 IPv6 几十毫秒的“起跑优势”来实现全球网络向下一代协议的平滑过渡。

### 下载(curl wget)

那我们如果想从微服的终端下载东西呢,有 curl 和 wget。通常来讲,curl 用来请求 API,比如测试接口,如果你的懒猫微服里发布了 API 可以用 curl 简单地测试;而 wget 主要用来下载文件。直接在微服上下载,比先下到电脑再 SFTP 传过去快多了。

```
curl -X POST https://api.example.com/login \
     -H "Content-Type: application/json" \
     -d '{"username": "admin", "password": "123"}'
```

```
wget https://example.com/file.zip
```

好了,接下来就是端口。

端口是一个逻辑概念,用于标识计算机上的不同服务。每个服务都会监听特定的端口,当有请求到达该端口时,系统会将请求转发给对应的服务。例如,HTTP 服务通常监听 80 端口,HTTPS 服务监听 443 端口,SSH 服务监听 22 端口。

在懒猫微服中,由于服务大多运行在容器中,所以似乎只有使用 pg-docker 的时候才会注意到端口,或者在终端里临时启动 web server:

```
lzcbox-e66ccc4a ~ # python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
```

那么我们如何知道哪些端口被占用呢?可以使用 netstat 或 ss 命令来查看。懒猫微服上容器多、服务杂,有时候端口冲突了,用这俩命令一查便知。我通常使用 `-nltp`:

**参数解释:**
- `-n` 显示数字端口(不解析服务名)
- `-l` 只看监听状态
- `-t` 只看 TCP
- `-p` 显示进程信息

```bash
ss -nltp | grep 8000
netstat -nltp | grep 8000
```

```bash
lzcbox-e66ccc4a ~ # ss -nltp | grep 8000
LISTEN 0      5                                     0.0.0.0:8000       0.0.0.0:*    users:(("python",pid=618243,fd=3))
```

> 日常用 `ss` 就行,更快。老系统或习惯了 `netstat` 也没问题,结果基本一样。

你可能也会看到其他人使用 lsof,同样可以查端口。lsof 除了查询端口之外,还能查询文件、进程等,这里不再赘述。

```bash
apt update && apt install lsof
lsof -i :8000
```

![image.png](https://dl.playground.lazycat.cloud/guidelines/459/f3751860-5652-4969-99e8-c7507184d191.png)

### 测试远程端口:telnet 和 nc

知道端口被谁占了,下一步就是测试远程端口通不通。比如你在懒猫微服上起了个服务,想从电脑上确认能不能连上。

telnet 是最经典的方式:

```
apt install telnet 

lzcbox-e66ccc4a ~ # telnet 192.168.8.1 22
Trying 192.168.8.1...
Connected to 192.168.8.1.
Escape character is '^]'.
SSH-2.0-dropbear
```

这就是 telnet 的用处——能看到服务返回的 banner 信息,做简单的服务识别。退出方式:按 `Ctrl + ]` 进入命令模式,然后输入 `quit`。

nc(netcat)更灵活,可以批量扫描端口:

```bash
nc -zv 192.168.8.1 20-100 2>&1 | grep succeeded

Connection to 192.168.8.1 22 port [tcp/ssh] succeeded!
Connection to 192.168.8.1 53 port [tcp/domain] succeeded!
Connection to 192.168.8.1 80 port [tcp/http] succeeded!
```


### 路径追踪:mtr 和 traceroute

端口通了,但网络还是慢?那就要看看路径上哪一跳出了问题。比如你从懒猫微服访问外网资源很慢,想知道是家里路由器的问题还是运营商的问题。

```bash
apt install mtr traceroute
```

网络不通的时候,光 ping 只能告诉你"不通",但不知道卡在哪一跳。这时候就需要 traceroute 或 mtr。

traceroute 是单次探测,跑一遍就结束:

```bash
traceroute baidu.com
```

mtr 更强,结合了 ping 和 traceroute,持续发包,实时显示每一跳的丢包率和延迟:

```bash
mtr baidu.com
```

网络时好时坏的时候,traceroute 可能刚好跑的时候没问题就抓不到,mtr 跑几分钟就能看到哪一跳在丢包。日常排查推荐用 mtr。

### 抓包:tshark

和 tcpdump 相比,tshark 的协议解析能力更强,能直接看到 HTTP 请求内容,而 tcpdump 只能看到十六进制。

懒猫微服上跑着各种服务,有时候想看看某个应用到底在发什么请求、收什么响应,tshark 就派上用场了。

懒猫的系统环境如果默认没装 tshark,需要使用这个命令进行安装

```
apt update && apt install -y tshark
```

用 tshark 抓一个本地 HTTP 请求,看看 TCP/HTTP 到底是怎么通信的。先在一个终端启动抓包:

```bash
# 抓 lo 回环接口(本机访问本机走这里)
tshark -i lo -f "port 8000"
```

然后另一个终端访问 `curl localhost:8000`,抓到 12 个包:

```
tshark -i lo -f "port 8000"
Running as user "root" and group "root". This could be dangerous.
Capturing on 'Loopback: lo'
 ** (tshark:1297291) 16:39:23.579519 [Main MESSAGE] -- Capture started.
 ** (tshark:1297291) 16:39:23.579553 [Main MESSAGE] -- File: "/tmp/wireshark_loK51JK3.pcapng"
    1 0.000000000 192.168.8.145 → 192.168.8.145 TCP 74 59548 → 8000 [SYN] Seq=0 Win=65495 Len=0 MSS=65495 SACK_PERM TSval=665319807 TSecr=0 WS=1024
    2 0.000007817 192.168.8.145 → 192.168.8.145 TCP 74 8000 → 59548 [SYN, ACK] Seq=0 Ack=1 Win=65483 Len=0 MSS=65495 SACK_PERM TSval=665319807 TSecr=665319807 WS=1024
    3 0.000012956 192.168.8.145 → 192.168.8.145 TCP 66 59548 → 8000 [ACK] Seq=1 Ack=1 Win=65536 Len=0 TSval=665319807 TSecr=665319807
    4 0.000035036 192.168.8.145 → 192.168.8.145 HTTP 148 GET / HTTP/1.1
    5 0.000036994 192.168.8.145 → 192.168.8.145 TCP 66 8000 → 59548 [ACK] Seq=1 Ack=83 Win=65536 Len=0 TSval=665319807 TSecr=665319807
    6 0.000801645 192.168.8.145 → 192.168.8.145 TCP 221 HTTP/1.0 200 OK  [TCP segment of a reassembled PDU]
    7 0.000813247 192.168.8.145 → 192.168.8.145 TCP 66 59548 → 8000 [ACK] Seq=83 Ack=156 Win=65536 Len=0 TSval=665319808 TSecr=665319808
    8 0.000834148 192.168.8.145 → 192.168.8.145 HTTP 976 HTTP/1.0 200 OK  (text/html)
    9 0.000837352 192.168.8.145 → 192.168.8.145 TCP 66 59548 → 8000 [ACK] Seq=83 Ack=1066 Win=65536 Len=0 TSval=665319808 TSecr=665319808
   10 0.000857121 192.168.8.145 → 192.168.8.145 TCP 66 8000 → 59548 [FIN, ACK] Seq=1066 Ack=83 Win=65536 Len=0 TSval=665319808 TSecr=665319808
   11 0.000901652 192.168.8.145 → 192.168.8.145 TCP 66 59548 → 8000 [FIN, ACK] Seq=83 Ack=1067 Win=65536 Len=0 TSval=665319808 TSecr=665319808
   12 0.000914845 192.168.8.145 → 192.168.8.145 TCP 66 8000 → 59548 [ACK] Seq=1067 Ack=84 Win=65536 Len=0 TSval=665319808 TSecr=665319808
```

针对上图的结果,我也总结了一个流程图,请看:

```
客户端 (59548)                    服务端 (8000)
    |                                  |
    |  -------- [SYN] --------->       |  1. 请求连接
    |         |  3. 确认
    |                                  |
    |  ===== 连接建立 =====            |
    |                                  |
    |  ---- GET / HTTP/1.1 ---->       |  4. 发请求
    |         |  9. 确认
    |                                  |
    |  ===== 数据传完 =====            |
    |                                  |
    |         |  11. 客户端关闭
    |  <-------- [ACK] ---------       |  12. 最终确认
    |                                  |
    |  ===== 连接关闭 =====            |
```



TCP 三次握手(建立连接)

```
1  59548 → 8000 [SYN]      "我想连接你"
2  8000 → 59548 [SYN,ACK]  "好的,我也准备好了"
3  59548 → 8000 [ACK]      "收到,开始通信"
```

为什么要三次?确保双方都能收发。两次不够——服务端不知道客户端能不能收到它的回复。

HTTP 请求/响应

```
4  GET / HTTP/1.1          客户端请求首页
5  [ACK]                   服务端确认收到
6-8  HTTP/1.0 200 OK       服务端返回网页
9  [ACK]                   客户端确认收到
```
TCP 四次挥手(关闭连接)

```
10  [FIN,ACK]  服务端 → 客户端  "我发完了"
11  [FIN,ACK]  客户端 → 服务端  "我也发完了"
12  [ACK]      服务端 → 客户端  "好的,再见"
```

虽然抓包看只有三行,但逻辑上它们依然是四次挥手的变体。

一共 12 个包,一次完整的 HTTP 请求就完成了。

### 尾声

网络之道,说繁亦繁,说简亦简。繁在协议层层叠叠,简在万变不离其宗——包从哪来,到哪去。

能用 tshark 看懂三次握手,用 mtr 定位丢包,用 ss 追溯端口归属,便已胜过大多数人。

所谓高手,不过是在无数次折腾中,把书本上的知识化作了指尖的肌肉记忆。

而懒猫微服,恰是这样一方天地——自带穿透,容器隔离,root 权限在握,尽可放手施为。纵有闪失,重置便是,不伤筋骨。

这大概就是它最大的魅力:不只是一台 NAS,更是折腾 infra、钻研安全的瑞士军刀。

所有的好奇心,皆有安放之处。

评论

0

暂无评论

说点什么呢~
收藏
0
0
0