前面八章的每一个协议,都默认「对面是善意的」。 这一章把这个假设拿掉,看这套协议在坏人面前是什么样子。
这是全书的最后一章,也是唯一一章不教「协议怎么工作」的。 它教的是「协议哪里会出事」。 Demo 从最原始的一步开始:在一台机器上扫一遍端口,看有多少门是开着的。
一、最初的互联网里没有「安全」这个词
TCP/IP 诞生在一个封闭的圈子里: 连在上面的都是几所大学和几个实验室,彼此认识,谁也不打算骗谁。 所以协议设计时根本没考虑认证——IP 头里那个源地址,是发送方自己填的。 这句话的后果比听起来严重:任何人都可以把源地址填成别人的,收方没有任何办法核实。 TCP 的三次握手证明的也只是「这个地址能收发报文」,不是「对面就是它自称的那台机器」。 于是安全能力只能一层一层往上加: TLS 加在 TCP 之上,IPsec 加在 IP 之上,802.1X 加在链路层上。 每一层加的时候都只能补自己那一块,这正是理解网络安全的第一把钥匙。
二、三件事,外加一件
所有安全目标可以拆成三条,业内叫 CIA 三元组:
| 目标 | 意思 | 被破坏的样子 |
|---|---|---|
| 机密性 | 别人看不见 | 明文被抓包 |
| 完整性 | 改了能发现 | 内容被替换 |
| 可用性 | 想用就能用 | 被打到连不上 |
这三条经常互相打架:要机密就得加密,加密就要算力;要完整就得校验,校验就要额外字节; 要可用就得留余量,留余量就意味着浪费。 所以安全从来没有「做到最好」,只有「权衡到能接受」。 第四条不在 CIA 里,但实战中最要紧:认证。 「你是谁」这件事,机密性回答不了—— 加密能保证「中间人看不见」,却保证不了「对面不是中间人」。 所以完整的说法是四条:机密、完整、可用、可认证。 最后说一句实话: 真实世界里绝大多数事故不是「被高手攻破」,而是「该打的补丁没打、该关的端口没关」。 这也解释了为什么下面这一节要从端口扫描开始。
三、加密加在哪一层,保护就到哪一层
这是本章最实用的一个视角:
| 层次 | 手段 | 保护到哪儿为止 |
|---|---|---|
| 应用层 | HTTPS、SSH、S/MIME | 端到端,中间看不见 |
| 传输层 | TCP 本身没有加密 | 只能靠上层补 |
| 网络层 | IPsec | 网关到网关,应用无感 |
| 链路层 | 802.1X、WPA | 只管这一段线 |
第三行是 IPsec 的价值:它加在 IP 上,所以上层应用完全不知道它在, 老系统不用改一行代码就能被保护。 代价是它只保护「网关到网关」,进了内网之后就是明文了。 第一行是 HTTPS 的边界:它保护到「浏览器到服务器」, 所以在公司里,如果中间有一个解密设备,那一段就不是端到端的了, 浏览器地址栏上的锁,说的是「这一段被加密过」,而不是「这个网站是好人」。
四、动手 Demo:一次端口扫描,看的是「谁在听」
在本机临时开三个端口,再把前 256 个端口扫一遍,看扫出来的和实际开着的差在哪儿。
import socket, time
hold = []
for _ in range(3):
s = socket.socket()
s.bind(("127.0.0.1", 0)) # 0 表示让系统分配
s.listen(5)
hold.append(s)
t0 = time.time()
opened = []
for p in range(1, 257):
c = socket.socket()
c.settimeout(0.002)
if c.connect_ex(("127.0.0.1", p)) == 0:
opened.append(p)
c.close()
print(len(opened), opened, round(time.time() - t0, 2), "秒")
实跑输出:
--------------------------------------------------------------------
一次端口扫描,看的是「谁在听」
--------------------------------------------------------------------
**安全的第一步不是加密,是知道有哪些门开着。**
**下面在本机临时开三个端口,再把前 256 个端口扫一遍。**
项目 结果
-------------------------------------------------------
扫描范围 **1 ~ 256**
耗时 **4.01 秒**
临时监听 **3 个:51175、51176、51177**
扫到的开放口 **1 个:135**
扫描是否看见临时端口 **没看见**
**最后一行是这段代码最该记住的地方**:**我明明开了三个端口,扫描却一个都没看见。**
**因为临时端口从 49152 起编号,全在 1 ~ 256 之外。**
**这就是扫描的第一个死穴:范围选窄了,等于闭着眼睛说「没有」。**
**四类威胁正好对应四种「门」**:
威胁 破坏什么 怎么发生 前提
------------------------------------------------------------------------
**窃听** **机密性** **链路被复制,内容被读** **明文协议**
**篡改** **完整性** **内容被改,双方都不知道** **无校验和**
**冒充** **认证** **对面不是它自称的那台** **只认地址**
**淹没** **可用性** **服务还在,但谁也连不上** **没有限速**
**端口扫描动的是最后一行**:**它不读内容、不改内容,只是把「哪里能连」画成一张地图。**
**而这张地图正是后面所有攻击的起点**——**先知道 135 开着,才知道该试什么。**
**所以防护的第一条不是「上加密」,而是「关掉不用的端口」。**
表里最扎眼的一行是「扫描是否看见临时端口:没看见」。 我明明开了三个端口,扫了一遍却一个都没扫到—— 因为系统分配的临时端口从 49152 起,全在 1 到 256 之外。 这就是扫描的第一个死穴:范围选窄了,等于闭着眼睛说「这里什么都没有」。 真实巡检里「扫完说没开放」和「根本没扫到」是两件事,所以专业的扫描器一定会报「扫了哪些端口」。 扫到的那个 135 是 Windows 的远程过程调用端口,它默认就开着,而且很少人知道该不该关。 一台机器上「默认开着、没人管、有历史漏洞」的端口,就是攻击面这个词的具体含义。
30 秒实验
- 算一下:65535 个端口全扫,按每 256 个用 4 秒估,串行要多久?(约 1024 秒,十七分钟; 并发能压到几秒)
- 想一下:为什么 IP 头里的源地址不能当身份用?
- 想一下:TLS 能防住端口扫描吗?(不能,它只管内容)
常见误区
- 以为「上了 HTTPS 就安全了」。 它只管机密性和完整性,不管端口暴露,也不管可用性。
- 以为「源地址就是身份」。 它是发送方自己填的,伪造源地址是拒绝服务攻击的常用手法。
- 以为「安全是一个可以加装的功能」。 它是每一层各自的取舍,加在哪一层,保护就到哪一层。
自测三问(点开对答案)
1. CIA 三元组是哪三条? —— **机密性、完整性、可用性**,实战还要加一条「可认证」。 2. 为什么 IP 层天生没有认证? —— **设计时是封闭圈子,源地址由发送方自填**,协议里没有核实字段。 3. 「加密加在哪一层,保护就到哪一层」怎么理解? —— **HTTPS 保护到服务器为止,出了那一段就是明文**;IPsec 保护到网关为止。下一节看第一道门:防火墙。它不是「判断对错」,而是一张有顺序的清单。
- ☐ (本节完,下一节 9.2.1 防火墙)