网络协议与安全
网络协议与安全 -- 从入门到实战
目录
- IP地址 -- 网络世界的门牌号
- TCP/IP协议 -- 数据快递的工作流程
- iptables防火墙 -- 经典门卫系统
- firewalld防火墙 -- 新一代智能门禁
- VPN虚拟专用通道 -- 公网中的秘密隧道
- 中间人攻击 -- 当心有人偷听你的对话
- sudo权限管理 -- 不是所有钥匙都要交给一个人
- SELinux -- 给系统穿上防弹衣
1. IP地址 -- 网络世界的门牌号
生活中的类比
想象一下:你住在一栋公寓楼里。你家的地址由两部分组成——小区名称(表示你住在哪个小区)和楼栋门牌号(表示你是小区里的哪一户)。
IP地址也是如此:它由 网络号(NetID) 和 主机号(HostID) 两部分组成。网络号标识你属于哪个网络,主机号标识你是该网络中的哪台设备。
1.1 IPv4地址结构
问题: 计算机是如何用一串数字来标识全球数十亿台设备的?
解答: IPv4地址是一个 32位的二进制数,为了方便人类阅读,我们把它分成4段,每段8位(1个字节),转换成十进制数,用小数点隔开。这种写法叫做 点分十进制表示法。
二进制形式: 11000000 . 10101000 . 00000001 . 00000001
十进制形式: 192 . 168 . 1 . 1
每段的取值范围是 0~255(因为8位二进制最大值为11111111 = 255)。
所以一个IPv4地址总共有 2^32 = 4,294,967,296 个可能的地址。
数学联系: 这里涉及到了二进制与十进制的转换,以及排列组合。32位地址空间 = 2^32 种组合,这就是IPv4地址总量约43亿个的由来。
1.2 IP地址的分类
问题: 全世界有大大小小的网络,有的公司只有一百台电脑,有的运营商有上百万台设备。怎么合理分配地址?
解答: 早期的互联网将IP地址划分为 A、B、C、D、E 五类,以适应不同规模的网络需求。
| 类别 | 首位特征 | 第一段范围 | 默认子网掩码 | 网络数 | 每网络最大主机数 | 适用场景 |
|---|---|---|---|---|---|---|
| A类 | 0 | 1~126 | 255.0.0.0 (/8) | 126 | 16,777,214 | 超大型网络 |
| B类 | 10 | 128~191 | 255.255.0.0 (/16) | 16,384 | 65,534 | 中型网络 |
| C类 | 110 | 192~223 | 255.255.255.0 (/24) | 2,097,152 | 254 | 小型网络 |
| D类 | 1110 | 224~239 | -- | -- | -- | 组播地址 |
| E类 | 11110 | 240~254 | -- | -- | -- | 保留实验 |
数学联系: 主机数的计算公式是 2^n - 2,其中n是主机号的位数。减2是因为:
- 全0的主机号 = 网络地址本身(如192.168.1.0)
- 全1的主机号 = 广播地址(如192.168.1.255)
例如C类地址:主机号8位,可用主机 = 2^8 - 2 = 254个。
特殊地址须知:
127.0.0.0/8:环回地址,用于本机测试(127.0.0.1= localhost)169.254.0.0/16:当DHCP失败时,系统自动分配的临时地址0.0.0.0:表示当前主机或默认路由
1.3 子网掩码与CIDR
问题: 一个C类网络有254个可用地址。如果我只需要50个地址,剩下的200多个不就浪费了吗?
解答: 这就是 子网划分(Subnetting) 要解决的问题。我们通过借用主机号中的一些位来作为子网号,从而把一个大的网络分割成多个小的子网。
子网掩码就是用来标识IP地址中哪些位是网络号(含子网号)、哪些位是主机号的。掩码中 1 对应的位是网络部分,0 对应的位是主机部分。
计算示例
题目: IP地址为 192.168.1.130,子网掩码为 255.255.255.192,求该IP所在的网络地址、广播地址和可用主机范围。
解题步骤:
第一步:将掩码转为二进制,确定主机位数
255.255.255.192 = 11111111.11111111.11111111.11000000
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
网络部分(26位) 主机部分(6位)
第二步:CIDR表示法 → /26 (26个1)
第三步:IP与掩码做AND运算,得到网络地址
IP: 192.168.1. 10000010
掩码: 255.255.255.11000000
AND: 192.168.1. 10000000 = 192.168.1.128
第四步:主机位全0 → 网络地址: 192.168.1.128
主机位全1 → 广播地址: 192.168.1.10111111 = 192.168.1.191
第五步:可用主机范围
起始: 192.168.1.129
结束: 192.168.1.190
可用主机数: 2^6 - 2 = 62台
常见子网划分速查表
| CIDR | 子网掩码 | 可用主机数 | 子网数量(C类中) |
|---|---|---|---|
| /24 | 255.255.255.0 | 254 | 1 |
| /25 | 255.255.255.128 | 126 | 2 |
| /26 | 255.255.255.192 | 62 | 4 |
| /27 | 255.255.255.224 | 30 | 8 |
| /28 | 255.255.255.240 | 14 | 16 |
| /29 | 255.255.255.248 | 6 | 32 |
| /30 | 255.255.255.252 | 2 | 64 |
课堂练习: 某学校需要将一个C类网络
192.168.10.0/24划分为4个子网,每个子网至少能容纳50台主机。请问子网掩码应设为多少?答案: 需要4个子网 → 借用2位主机位 → /26 → 掩码255.255.255.192,每个子网可用主机 2^6 - 2 = 62 > 50,满足需求。
1.4 私有IP与公网IP
问题: IPv4只有43亿个地址,全世界设备远不止这个数,怎么办?
解答: 使用 私有IP地址(Private IP)。私有IP在局域网内部使用,不需要全球唯一,多个不同的局域网可以使用相同的私有IP段。当需要访问互联网时,通过 NAT(网络地址转换) 将私有IP转换为公网IP。
| 类别 | 私有IP范围 | CIDR表示 | 可用地址数 |
|---|---|---|---|
| A类 | 10.0.0.0 ~ 10.255.255.255 | 10.0.0.0/8 | 约1677万 |
| B类 | 172.16.0.0 ~ 172.31.255.255 | 172.16.0.0/12 | 约104万 |
| C类 | 192.168.0.0 ~ 192.168.255.255 | 192.168.0.0/16 | 约6.5万 |
生活类比: 私有IP就像公司内部的分机号(如8001、8002),不同公司的分机号可以重复使用。公网IP才是对外的总机号码。
1.5 实用命令:ip命令替代ifconfig
# 查看网卡信息(含MAC地址、MTU等)
ip link show
ip -s link show eth0 # -s 显示数据包统计
# 启用/禁用网卡
ip link set eth0 up
ip link set eth0 down
# 修改MTU(最大传输单元,默认1500字节)
ip link set eth0 mtu 1400
# 查看IP地址
ip addr show
# 添加/删除IP地址(临时生效)
ip addr add 192.168.50.50/24 dev eth0
ip addr del 192.168.50.50/24 dev eth0
# 查看路由表
ip route show
# 添加默认网关
ip route add default via 192.168.1.1
# 添加静态路由
ip route add 10.10.10.0/24 via 192.168.1.254
# 查看ARP缓存(IP与MAC的映射表)
ip neigh show
提示:
ip命令的修改是 临时 的,重启后失效。永久修改需要编辑网卡配置文件(如/etc/sysconfig/network-scripts/ifcfg-eth0)。
2. TCP/IP协议 -- 数据快递的工作流程
生活中的类比
把网络通信想象成 寄快递:
- 物理层 = 公路和卡车(实际运输的工具)
- 数据链路层 = 快递分拣站(负责相邻站点间的传递)
- 网络层 = 快递路由系统(决定包裹从北京到上海走哪条路线)
- 传输层 = 快递保险服务(TCP=保价快递,丢件必赔;UDP=明信片,丢了不管)
- 应用层 = 你寄的具体物品(网页、文件、邮件等)
2.1 OSI七层模型与TCP/IP模型
问题: 网络通信涉及硬件、软件、协议等众多环节,如何理解和管理这种复杂性?
解答: 采用 分层模型,每一层只负责一个特定的功能,层与层之间通过接口交互。这和数学中的 函数复合 思想相似——f(g(h(x))),每个函数只做一件事。
┌─────────────────────────────────────────────┐
│ OSI七层模型 │
│ │
│ ┌──────────┐ ┌────────────────────────┐ │
│ │ 应用层 │←──→│ 应用层(HTTP/FTP/SSH) │ │
│ ├──────────┤ ├────────────────────────┤ │
│ │ 表示层 │ │ │ │
│ ├──────────┤ │ TCP/IP四层模型 │ │
│ │ 会话层 │←──→│ │ │
│ ├──────────┤ ├────────────────────────┤ │
│ │ 传输层 │←──→│ 传输层(TCP/UDP) │ │
│ ├──────────┤ ├────────────────────────┤ │
│ │ 网络层 │←──→│ 网络层(IP/ICMP/ARP) │ │
│ ├──────────┤ ├────────────────────────┤ │
│ │ 数据链路 │←──→│ 数据链路层+物理层 │ │
│ ├──────────┤ │ (以太网/WiFi) │ │
│ │ 物理层 │ └────────────────────────┘ │
│ └──────────┘ │
└─────────────────────────────────────────────┘
实际工作中,我们通常使用简化的TCP/IP四层模型。OSI七层模型主要用于教学和理论讨论。
2.2 TCP三次握手 -- 建立可靠连接
问题: 两台电脑要开始通信了,怎么确保双方都准备好了?
解答: TCP使用 三次握手(Three-way Handshake) 来建立连接。
生活类比: 打电话的过程就是"三次握手"
- 你拨号 → 对方接起来 → 你说"喂,听得见吗?" → 对方说"听得见" → 你说"好的" → 开始聊正事
客户端 (Client) 服务器 (Server)
│ │
│──── 1. SYN (seq=x) ──────────────→│ "我想和你通信"
│ │
│←─── 2. SYN+ACK (seq=y, ack=x+1) ──│ "好的,我也想和你通信"
│ │
│──── 3. ACK (ack=y+1) ────────────→│ "收到,我们开始吧"
│ │
│══════════ 连接建立,开始传输数据 ══════════│
关键标志位:
| 标志 | 含义 | 类比 |
|---|---|---|
| SYN | 同步(Synchronize),发起连接 | 拨号 |
| ACK | 确认(Acknowledgment),确认收到 | "收到" |
| FIN | 结束(Finish),关闭连接 | "挂了" |
| RST | 重置(Reset),强制断开 | 直接挂断电话 |
| PSH | 推送(Push),立即传递数据 | "这个急,马上看" |
| URG | 紧急(Urgent),紧急数据优先处理 | "十万火急" |
2.3 TCP四次挥手 -- 断开连接
客户端 服务器
│ │
│──── 1. FIN ──────────────────────→│ "我说完了"
│←─── 2. ACK ──────────────────────│ "收到你说完了"
│ │ (服务器可能还有数据要发)
│←─── 3. FIN ──────────────────────│ "我也说完了"
│──── 4. ACK ──────────────────────→│ "好的,拜拜"
│ │
│ (等待2MSL时间后关闭) │ (收到ACK后立即关闭)
为什么是四次而不是三次? 因为TCP是 全双工 通信(双方可以同时发送和接收),每个方向必须独立关闭。就像挂电话——你说完了不代表对方也说完了。
2.4 TCP vs UDP
| 特性 | TCP(挂号信) | UDP(明信片) |
|---|---|---|
| 连接方式 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(确认、重传) | 不可靠 |
| 速度 | 较慢 | 较快 |
| 首部长度 | 20~60字节 | 8字节 |
| 适用场景 | 网页、文件传输、SSH | 视频通话、DNS查询、游戏 |
类比: TCP就像挂号信——有回执、保证送到、但费用高速度慢。UDP就像明信片——便宜快速、但不保证对方能收到。视频通话偶尔丢一两帧画面无所谓,所以用UDP;但下载文件一个字节都不能丢,所以必须用TCP。
2.5 常见端口速查
| 端口 | 协议 | 用途 | 传输层 |
|---|---|---|---|
| 20/21 | FTP | 文件传输(20=数据,21=控制) | TCP |
| 22 | SSH | 远程安全登录 | TCP |
| 23 | Telnet | 远程登录(明文,不安全) | TCP |
| 25 | SMTP | 发送邮件 | TCP |
| 53 | DNS | 域名解析 | UDP/TCP |
| 80 | HTTP | 网页浏览 | TCP |
| 110 | POP3 | 接收邮件 | TCP |
| 443 | HTTPS | 加密网页 | TCP |
| 3306 | MySQL | 数据库 | TCP |
| 8080 | HTTP-Alt | Web代理/备用HTTP | TCP |
2.6 数据包流动全过程 -- 以ping为例
问题: 当你在电脑上输入 ping www.baidu.com 时,到底发生了什么?
解答: 让我们用 tcpdump 抓包工具来一探究竟。
# 安装抓包工具
yum install -y tcpdump
# 抓取ping的数据包(ICMP协议)
tcpdump -i eth0 -nn icmp and host 192.168.1.1
# 抓取指定端口的TCP数据包
tcpdump -i eth0 -nn -S host 192.168.1.1 and port 80
# 保存抓包结果到文件(可用Wireshark分析)
tcpdump -i eth0 -nn -w /tmp/capture.pcap host 192.168.1.1
一次ping的完整过程:
1. DNS解析: www.baidu.com → 180.101.50.242(使用UDP 53端口)
2. ARP查询: 180.101.50.242 的MAC地址是什么?(广播FF:FF:FF:FF:FF:FF)
3. ARP应答: 网关回复自己的MAC地址
4. 构造ICMP Echo Request(类型8),封装到IP数据报
5. 数据报 → 数据链路层封装以太网帧 → 物理层发送
6. 沿途路由器根据IP头部TTL逐跳转发
7. 目标收到后回复ICMP Echo Reply(类型0)
8. 本机收到回复,显示延迟时间
ICMP协议重点类型:
| Type | Code | 含义 | 常见触发场景 |
|---|---|---|---|
| 8 | 0 | Echo Request(ping请求) | 你ping别人 |
| 0 | 0 | Echo Reply(ping回复) | 别人回你 |
| 3 | 0 | 网络不可达 | 路由找不到目标网段 |
| 3 | 1 | 主机不可达 | 路由找到网段但找不到主机 |
| 3 | 3 | 端口不可达 | 目标主机上该端口未开放 |
动手实验: 使用
tcpdump抓取ARP包,观察MAC地址解析过程:# 先清空ARP缓存 arp -d # 然后抓包并ping tcpdump -i eth0 -nn arp & ping -c 1 192.168.1.1
2.7 ARP协议 -- IP与MAC的桥梁
问题: 网络层用IP地址寻址,但以太网实际传输时用的是MAC地址(物理地址)。如何把IP转换为MAC?
解答: ARP(Address Resolution Protocol,地址解析协议) 就是完成这个翻译工作的。
类比: 你知道收件人的名字(IP地址),但快递员需要具体的门牌号(MAC地址)才能送达。ARP就像是你在小区群里喊了一声:"张三家住几号楼几单元?"——这就是ARP广播。
ARP工作流程:
1. 本机检查ARP缓存表,看有没有目标IP对应的MAC
2. 如果没有 → 发送ARP广播: "谁是192.168.1.1?请告诉我你的MAC"
3. 目标主机回复: "我是192.168.1.1,我的MAC是 AA:BB:CC:DD:EE:FF"
4. 本机更新ARP缓存表
# 查看ARP缓存表
arp -n
# 或者
ip neigh show
# 手动绑定IP和MAC(防止ARP欺骗)
arp -s 192.168.1.1 AA:BB:CC:DD:EE:FF
3. iptables防火墙 -- 经典门卫系统
生活中的类比
把防火墙想象成 公寓大楼的保安:
- 保安手里有一份 访客规则表(规则链)
- 每个来访者都要对照规则表逐条检查
- 规则从上到下匹配,一旦匹配就执行对应动作,不再继续往下查
- 如果所有规则都不匹配,就按 默认策略 处理(默认放行或默认拒绝)
iptables的工作方式就是这样——数据包进入后,依次匹配规则,匹配到就执行动作。
3.1 基础架构:表、链、规则
问题: 防火墙如何决定一个数据包是放行还是丢弃?
解答: iptables的核心架构是 表(Table)→ 链(Chain)→ 规则(Rule) 三级结构。
┌─────────────────────────────────────────────────────┐
│ iptables 规则处理流程 │
│ │
│ 数据包进入 │
│ │ │
│ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌───────┐ ┌────────┐│
│ │ raw表 │→│ mangle表 │→│ nat表 │→│filter表││
│ └─────────┘ └─────────┘ └───────┘ └────────┘│
│ │
│ 各表中的链: │
│ │
│ PREROUTING ─── 数据包刚进入,还未路由 │
│ │ │
│ ▼ │
│ [路由判断] ──→ 是发给本机的? │
│ │ │ │
│ │ 不是(转发) │
│ │ │ │
│ ▼ ▼ │
│ INPUT链 FORWARD链 │
│ │ │ │
│ ▼ ▼ │
│ 本机进程 OUTPUT链 │
│ │ │ │
│ ▼ ▼ │
│ POSTROUTING链 ─── 数据包即将离开 │
│ │
└─────────────────────────────────────────────────────┘
四张表的作用:
| 表名 | 用途 | 常用链 |
|---|---|---|
| filter | 过滤数据包(最常用) | INPUT, OUTPUT, FORWARD |
| nat | 地址转换(NAT) | PREROUTING, POSTROUTING, OUTPUT |
| mangle | 修改数据包标记 | PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING |
| raw | 在连接跟踪前处理 | PREROUTING, OUTPUT |
3.2 基本规则操作
# ===== 查看规则 =====
iptables -L -n -v --line-numbers # 查看filter表所有规则,显示行号
iptables -t nat -L -n -v # 查看nat表
# ===== 清除规则(慎用!先确保SSH不会被锁) =====
iptables -F # 清除filter表所有规则
iptables -t nat -F # 清除nat表所有规则
iptables -X # 删除自定义链
iptables -Z # 计数器清零
# ===== 添加规则 =====
# 语法: iptables [-t 表名] 操作 链名 匹配条件 -j 动作
# 禁止某IP访问本机
iptables -A INPUT -s 192.168.1.100 -j DROP
# 禁止某个网段访问
iptables -A INPUT -s 192.168.1.0/24 -j DROP
# 允许SSH访问(端口22)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 允许HTTP和HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# 禁止某IP的ICMP(不让ping)
iptables -A INPUT -s 192.168.1.100 -p icmp -j DROP
# ===== 插入规则(默认插到第1条) =====
iptables -I INPUT -p tcp --dport 22 -j ACCEPT # 插到最前面
iptables -I INPUT 3 -p tcp --dport 80 -j ACCEPT # 插到第3条
# ===== 删除规则 =====
iptables -D INPUT -s 192.168.1.100 -j DROP # 按内容删除
iptables -D INPUT 3 # 按行号删除
# ===== 设置默认策略 =====
iptables -P INPUT DROP # 默认丢弃所有进入的数据包
iptables -P FORWARD DROP # 默认不转发
iptables -P OUTPUT ACCEPT # 默认允许本机发出的数据包
3.3 实战:搭建一个安全防火墙脚本
场景: 一台对外提供Web服务(80/443)和SSH管理(22)的服务器。
#!/bin/bash
# === 安全防火墙配置脚本 ===
# 原则:默认拒绝一切,只放行必要的服务(最小权限原则)
# 第一步:先允许已建立的连接(防止把自己锁在外面)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 第二步:允许本地回环(很多服务依赖localhost通信)
iptables -A INPUT -i lo -j ACCEPT
# 第三步:放行SSH(管理用)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 第四步:放行HTTP和HTTPS(Web服务)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# 第五步:允许ping(可选,用于网络诊断)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# 第六步:设置默认策略为DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# 保存规则(CentOS 7)
iptables-save > /etc/sysconfig/iptables
3.4 状态防火墙(state模块)
问题: 我允许了别人访问我的80端口,那服务器返回的响应数据包不就被OUTPUT链的默认DROP策略拦截了吗?
解答: 这就是 状态防火墙 的精妙之处。它能"记住"连接的状态,自动放行已建立连接的响应包。
四种连接状态:
| 状态 | 含义 | 举例 |
|---|---|---|
| NEW | 新连接的第一个包 | 客户端发来的SYN |
| ESTABLISHED | 已建立的连接 | 三次握手后的所有数据包 |
| RELATED | 与已建立连接相关的新连接 | FTP数据连接 |
| INVALID | 无法识别的异常包 | 损坏的数据包 |
# 状态防火墙的标准写法(必学!)
# 放行所有已建立连接和相关连接的数据包
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 只放行新的SSH连接请求
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
# 只放行新的HTTP请求
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
3.5 高级匹配模块
# === IP地址范围匹配 ===
iptables -A INPUT -m iprange --src-range 192.168.1.10-192.168.1.50 -j DROP
# === MAC地址匹配 ===
iptables -A INPUT -m mac --mac-source 00:0C:29:AA:7A:ED -j DROP
# === 多端口匹配 ===
iptables -A INPUT -p tcp -m multiport --dports 22,80,443,8080 -j ACCEPT
# === 连接数限制(防止SSH暴力破解) ===
iptables -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j REJECT
# === 速率限制(防止ping flood攻击) ===
iptables -A INPUT -p icmp -m limit --limit 1/second --limit-burst 4 -j ACCEPT
iptables -A INPUT -p icmp -j DROP
# === SYN Flood防护 ===
iptables -A INPUT -p tcp --syn -m limit --limit 50/second -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
3.6 NAT地址转换
类比: NAT就像公司前台。外人只能看到公司总机号码(公网IP),当你打电话出去时,前台帮你转接(SNAT);当外面有人打总机找某个部门时,前台帮你转接到对应分机(DNAT)。
SNAT -- 让内网机器上网
# 场景: 内网192.168.1.0/24 通过 NAT服务器(公网IP: 1.1.1.1)上网
# 第一步:开启路由转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效: 在 /etc/sysctl.conf 中添加 net.ipv4.ip_forward = 1
# 第二步:配置SNAT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j SNAT --to-source 1.1.1.1
# 如果公网IP是动态的(如PPPoE拨号),使用MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 -j MASQUERADE
DNAT -- 端口转发(将外网流量转给内网服务器)
# 场景: 外网用户访问 1.1.1.1:80 → 转发给内网的Web服务器 192.168.1.100:80
iptables -t nat -A PREROUTING -i eth1 -d 1.1.1.1 -p tcp --dport 80 \
-j DNAT --to-destination 192.168.1.100:80
# 端口映射: 外网8080端口 → 内网服务器的80端口
iptables -t nat -A PREROUTING -p tcp --dport 8080 \
-j DNAT --to-destination 192.168.1.100:80
动手实验: 在两台虚拟机之间配置iptables规则,实现:
- 禁止同桌ping你的机器
- 但允许你ping同桌的机器
提示: 使用
-m icmp --icmp-type echo-request和--icmp-type echo-reply分别控制请求和响应。
4. firewalld防火墙 -- 新一代智能门禁
生活中的类比
如果iptables是保安拿着纸质名单逐条核对,那 firewalld 就是 智能门禁系统——
- 你可以根据不同场景切换 安全区域(在公司用办公规则,回家用家庭规则)
- 修改规则后 立即生效,不需要重启整个系统(不会断开现有连接)
- 支持 富规则(rich rules),用更接近自然语言的方式写规则
4.1 firewalld vs iptables
| 对比项 | iptables | firewalld |
|---|---|---|
| 规则变更 | 需要reload所有规则,断开现有连接 | 增量更新,不影响现有连接 |
| 配置方式 | 命令行直接操作 | 区域(Zone)+ 服务(Service) |
| 默认工具 | iptables命令 | firewall-cmd / firewall-config |
| 底层引擎 | 直接操作netfilter | 仍然是netfilter(firewalld是前端控制器) |
| 适用系统 | CentOS 6及以前 | CentOS 7/8, Fedora, RHEL |
重要理解: firewalld的底层仍然是iptables/netfilter,它只是一个更友好的 前端管理器。两者不能同时使用,需要选一个。
4.2 区域(Zone)概念
firewalld引入了 区域 的概念,每个区域代表不同的信任级别。
┌──────────────────────────────────────────────────┐
│ firewalld 区域模型 │
│ │
│ ┌─────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │ public │ │ internal │ │ trusted │ │
│ │ (公共区) │ │ (内部区) │ │ (完全信任区) │ │
│ │ 默认拒绝 │ │ 允许部分 │ │ 全部放行 │ │
│ └─────────┘ └──────────┘ └─────────────────┘ │
│ │
│ ┌─────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │ home │ │ work │ │ dmz │ │
│ │ (家庭区) │ │ (工作区) │ │ (隔离区) │ │
│ │ 允许部分 │ │ 允许部分 │ │ 仅允许指定服务 │ │
│ └─────────┘ └──────────┘ └─────────────────┘ │
│ │
│ ┌─────────┐ ┌──────────┐ ┌─────────────────┐ │
│ │external │ │ block │ │ drop │ │
│ │(外部区) │ │ (阻止区) │ │ (丢弃区) │ │
│ │ 含NAT │ │ 全部拒绝 │ │ 静默丢弃 │ │
│ └─────────┘ └──────────┘ └─────────────────┘ │
└──────────────────────────────────────────────────┘
| 区域 | 信任级别 | 典型用途 |
|---|---|---|
| trusted | 完全信任 | 测试环境、内部可信网络 |
| home | 较信任 | 家庭网络 |
| internal | 较信任 | 公司内部网络 |
| work | 较信任 | 办公网络 |
| public | 不信任(默认) | 互联网、公共WiFi |
| external | 不信任 | 路由器外网接口(含NAT伪装) |
| dmz | 不信任 | DMZ区域(对外服务器) |
| block | 拒绝 | 拒绝一切,返回icmp错误 |
| drop | 丢弃 | 静默丢弃一切,不回应 |
4.3 firewalld常用命令
# ===== 基础信息 =====
systemctl status firewalld # 查看状态
firewall-cmd --state # 是否运行中
firewall-cmd --get-default-zone # 查看默认区域
firewall-cmd --get-active-zones # 查看活跃区域及绑定的网卡
# ===== 服务管理 =====
# 查看当前区域已开放的服务
firewall-cmd --list-services
# 添加HTTP服务(临时生效,重启丢失)
firewall-cmd --add-service=http
# 永久添加HTTP和HTTPS服务
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
# 添加端口
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --permanent --add-port=3306/tcp
# 移除服务
firewall-cmd --permanent --remove-service=telnet
# 重新加载配置(永久规则生效)
firewall-cmd --reload
4.4 富规则(Rich Rules)
问题: 我需要更精细的控制——比如只允许特定IP段访问MySQL端口,firewalld的基本命令做不到。
解答: 使用 富规则(Rich Rules),语法更接近自然语言。
# 只允许192.168.1.0/24网段访问3306端口
firewall-cmd --permanent --add-rich-rule \
'rule family="ipv4" source address="192.168.1.0/24" port port="3306" protocol="tcp" accept'
# 拒绝某个IP的所有访问
firewall-cmd --permanent --add-rich-rule \
'rule family="ipv4" source address="10.0.0.100" drop'
# 限制SSH连接速率(每分钟最多3个新连接)
firewall-cmd --permanent --add-rich-rule \
'rule family="ipv4" service name="ssh" limit value="3/m" accept'
# 查看已配置的富规则
firewall-cmd --list-rich-rules
# 删除富规则
firewall-cmd --permanent --remove-rich-rule \
'rule family="ipv4" source address="10.0.0.100" drop'
4.5 实战:Web服务器防火墙配置
# 完整配置流程
# 1. 设置默认区域为public
firewall-cmd --set-default-zone=public
# 2. 允许SSH管理
firewall-cmd --permanent --add-service=ssh
# 3. 允许Web服务
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
# 4. 允许ICMP(ping)
# firewalld默认已允许ping,如被禁用可重新启用
firewall-cmd --permanent --remove-icmp-block=echo-request
# 5. 只允许特定IP段访问管理端口(富规则)
firewall-cmd --permanent --add-rich-rule \
'rule family="ipv4" source address="10.0.0.0/8" port port="22" protocol="tcp" accept'
# 6. 生效配置
firewall-cmd --reload
# 7. 验证
firewall-cmd --list-all
课堂讨论: 如果你的学校机房有一台Web服务器,既要让全校学生访问网站,又要限制只有管理员的IP段可以SSH登录,你会怎么配置防火墙?
5. VPN虚拟专用通道 -- 公网中的秘密隧道
生活中的类比
想象你在一条 繁忙的高速公路(互联网)上开车。所有人都能看到你的车牌号和你走哪条路。
VPN 就像在高速公路上建了一条 只有你知道入口的密封隧道。你的车进入隧道后,外面的人既看不到你走了哪条路,也看不到你车上装了什么。
技术上说:VPN在公共网络上创建一条 加密隧道,你的所有数据都通过这条隧道传输,外面的人即使截获了数据包,也无法解密。
5.1 为什么需要VPN?
| 场景 | 问题 | VPN解决方案 |
|---|---|---|
| 远程办公 | 员工在家需要访问公司内部服务器 | 通过VPN连接到公司内网 |
| 分支机构互联 | 北京和上海办公室需要互通 | 两端建立VPN隧道 |
| 公共WiFi安全 | 咖啡厅WiFi可能被窃听 | VPN加密所有流量 |
| 隐私保护 | ISP可能记录上网行为 | 流量通过VPN中转 |
5.2 OpenVPN基本原理
OpenVPN 是Linux下最流行的开源VPN方案,核心技术是:
- 虚拟网卡: 在系统中创建一个虚拟的网络接口
- SSL/TLS加密: 使用OpenSSL库加密数据与控制信息
- 隧道模式: TUN(三层IP隧道)或 TAP(二层以太网桥接)
┌─────────────────────────────────────────────────┐
│ OpenVPN 工作原理 │
│ │
│ 你的电脑 VPN服务器 │
│ ┌─────┐ 加密隧道 ┌─────────┐ │
│ │应用层│ ═══════════════ →│ 解密 │→ 内网资源 │
│ │数据 │ (SSL/TLS) │ 转发 │ │
│ └─────┘ └─────────┘ │
│ │
│ 默认端口: 1194/UDP │
│ 加密算法: AES, Blowfish, 3DES等 │
│ 压缩: LZO算法 │
│ 认证方式: 证书 / 预共享密钥 / 用户名密码 │
└─────────────────────────────────────────────────┘
5.3 OpenVPN服务端部署(证书认证方式)
# ===== 第一步:安装软件 =====
yum install -y epel-release
yum install -y openvpn easy-rsa
# ===== 第二步:初始化PKI证书体系 =====
cd /usr/share/easy-rsa/3.0.3/
./easyrsa init-pki # 初始化PKI目录
# ===== 第三步:创建CA证书(证书颁发机构) =====
./easyrsa build-ca # 按提示设置CA密码
# ===== 第四步:生成服务端证书和密钥 =====
./easyrsa build-server-full vpnserver # 生成服务端证书
# ===== 第五步:生成客户端证书 =====
./easyrsa build-client-full client1 # 为客户端1生成证书
# ===== 第六步:生成DH参数(密钥交换用) =====
./easyrsa gen-dh
# ===== 第七步:复制证书到OpenVPN配置目录 =====
cp pki/ca.crt pki/private/vpnserver.key pki/issued/vpnserver.crt /etc/openvpn/
cp pki/dh.pem /etc/openvpn/
# ===== 第八步:编辑服务端配置 =====
cp /usr/share/doc/openvpn-*/sample/sample-config-files/server.conf /etc/openvpn/server.conf
服务端配置文件关键参数:
# /etc/openvpn/server.conf 关键配置
local 0.0.0.0 # 监听所有网卡(或指定公网IP)
port 1194 # VPN端口
proto udp # 使用UDP协议(延迟高时改TCP)
dev tun # TUN模式(三层路由)
ca ca.crt # CA证书
cert vpnserver.crt # 服务端证书
key vpnserver.key # 服务端私钥
dh dh.pem # DH参数
server 10.8.0.0 255.255.255.0 # VPN内网网段
push "route 192.168.1.0 255.255.255.0" # 推送内网路由给客户端
keepalive 10 120 # 心跳检测:每10秒ping,120秒无响应认为断开
comp-lzo # 启用LZO压缩
max-clients 100 # 最大客户端数
user nobody # 降权运行(安全!)
group nobody
persist-key # 重启时保留密钥
persist-tun # 重启时保留隧道
# ===== 第九步:启动服务 =====
# 如果CA有密码,去掉私钥密码
openssl rsa -in /etc/openvpn/vpnserver.key -out /etc/openvpn/vpnserver.key
systemctl start openvpn@server
systemctl enable openvpn@server
# ===== 第十步:开启NAT转发(让VPN客户端能访问内网) =====
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -j MASQUERADE
5.4 OpenVPN客户端配置
# 客户端配置文件 /etc/openvpn/client.conf
client
dev tun
proto udp
remote vpn.example.com 1194 # VPN服务器地址
nobind
ca ca.crt
cert client1.crt
key client1.key
comp-lzo
persist-key
persist-tun
verb 3
# 启动客户端
openvpn --config /etc/openvpn/client.conf --daemon
# 验证连接
ip addr show tun0 # 应该看到10.8.0.x的虚拟IP
ping 10.8.0.1 # ping VPN服务器内网地址
5.5 TUN vs TAP模式选择
| 模式 | 工作层级 | 特点 | 适用场景 |
|---|---|---|---|
| TUN | 三层(IP层) | 只处理IP包,效率高 | 远程办公、上网 |
| TAP | 二层(以太网层) | 处理以太网帧,支持广播 | 网桥、游戏局域网 |
建议: 大多数场景下使用 TUN 模式,除非你需要传输非IP协议(如NetBIOS广播)。
6. 中间人攻击 -- 当心有人偷听你的对话
生活中的类比
你和朋友通过 信件 通信。正常情况下:你 → 邮局 → 朋友。
中间人攻击(MITM): 有个骗子冒充邮局工作人员,他拆开你的信看了一遍,然后重新封好送给你的朋友。你的朋友收到的信看起来完好无损,但内容已经被偷看了。更坏的情况是,骗子可能 篡改 了信的内容。
在网络世界中,ARP欺骗就是一种典型的中间人攻击手段。
6.1 中间人攻击的三种手段
┌──────────────────────────────────────────────────────────┐
│ 网络通信的三大威胁 │
│ │
│ 1. 窃听 (Eavesdropping) │
│ A ←────────────────────→ B │
│ ↑ 偷看 │
│ C │
│ 对策: 加密 (Encryption) │
│ │
│ 2. 篡改 (Tampering) │
│ A ←────→ C(修改内容)←────→ B │
│ 对策: 哈希校验 (Hash / HMAC) │
│ │
│ 3. 伪装 (Impersonation) │
│ A ←────→ C(冒充B) │
│ 对策: 数字证书 + CA认证 (Certificate) │
│ │
└──────────────────────────────────────────────────────────┘
6.2 ARP欺骗原理与防范
问题: ARP协议有个设计缺陷——它 无条件信任 收到的ARP应答,即使你没有发出请求。攻击者利用这个缺陷,向你发送伪造的ARP应答。
攻击过程:
正常情况:
A的ARP缓存: 192.168.1.1 (网关) → AA:BB:CC:DD:EE:FF (网关MAC)
攻击者C发送伪造ARP应答:
"我是192.168.1.1,我的MAC是 11:22:33:44:55:66"
被攻击后A的ARP缓存:
192.168.1.1 (网关) → 11:22:33:44:55:66 (攻击者C的MAC!)
结果: A发往网关的数据全部被C截获
防范措施:
# 方法1: 静态ARP绑定(简单有效)
# 将网关的IP和MAC永久绑定,不再接受动态更新
arp -s 192.168.1.1 AA:BB:CC:DD:EE:FF
# 方法2: 使用ARP防护工具
# 安装arpon等工具,持续监控ARP表变化
yum install -y arpon
# 方法3: 交换机端口安全(企业级方案)
# 在交换机上配置端口安全策略,阻止伪造ARP
6.3 加密技术 -- 防窃听
对称加密(一把钥匙)
类比: 你和朋友约定一个暗号(密钥),用这个暗号加密和解密信件。问题是——暗号怎么安全地告诉对方?
# 使用openssl进行对称加密(DES算法)
openssl enc -e -des -in /etc/passwd -out /tmp/passwd.des
# 输入加密密码
# 解密
openssl enc -d -des -in /tmp/passwd.des -out /tmp/passwd.dec
常见对称加密算法:DES(已过时)、3DES、AES(目前推荐)。
非对称加密(公钥+私钥)
类比: 你做一个特殊的 信箱——任何人都可以往里投信(用公钥加密),但只有你有钥匙打开信箱取出信(用私钥解密)。
# 使用GPG(GNU Privacy Guard)生成密钥对
# 第一步:生成密钥对
gpg --gen-key
# 按提示输入姓名、邮箱,选择RSA算法和2048位密钥长度
# 第二步:查看密钥
gpg --list-keys # 查看公钥
gpg --list-secret-keys # 查看私钥
# 第三步:导出公钥给朋友
gpg --export -armor yourname > /tmp/yourname.pub
# 第四步:朋友导入你的公钥
gpg --import < yourname.pub
# 第五步:朋友用你的公钥加密文件
gpg --encrypt --armor --recipient yourname secret.txt
# 第六步:你用自己的私钥解密
gpg --decrypt secret.txt.asc > secret_decrypted.txt
6.4 哈希校验 -- 防篡改
类比: 你在信末尾附一个 指纹(哈希值)。对方收到信后也计算一下指纹,如果两个指纹一致,说明信没被动过手脚。
哈希函数的三个特性:
- 确定性: 相同输入 → 相同输出(永远不变)
- 固定长度: 不管输入多长,输出长度固定
- 不可逆: 无法从哈希值反推原始内容
# 计算文件的MD5哈希值
md5sum /etc/passwd
# 输出: bffc5857b2cf07ed48dd2a7535f11a31 /etc/passwd
# 计算SHA256哈希值(更安全)
sha256sum /etc/passwd
# 下载文件后验证完整性
# 1. 从官网获取文件的官方SHA256值
# 2. 下载后自己计算SHA256值
# 3. 两者一致 = 文件没有被篡改
6.5 SSL/TLS与HTTPS -- 综合防护
问题: 对称加密快但密钥分发困难,非对称加密安全但速度慢。怎么兼顾?
解答: HTTPS = HTTP + SSL/TLS,它巧妙地结合了对称加密和非对称加密:
HTTPS 握手过程(简化版):
1. 客户端发起连接 → 服务器出示"身份证"(数字证书)
2. 客户端向CA机构核实证书真伪
3. 客户端生成一个随机密码(对称密钥),用服务器的公钥加密后发送
4. 服务器用私钥解密,得到对称密钥
5. 此后双方用这个对称密钥加密所有通信数据
总结: 非对称加密用来安全地交换密钥,对称加密用来高效地传输数据
动手实验: 使用
openssl创建自签名证书,配置Apache启用HTTPS:# 生成自签名证书 openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/httpd/ssl/server.key \ -out /etc/httpd/ssl/server.crt \ -subj "/CN=www.example.com" # 在Apache SSL配置中指定证书路径 # SSLCertificateFile /etc/httpd/ssl/server.crt # SSLCertificateKeyFile /etc/httpd/ssl/server.key
7. sudo权限管理 -- 不是所有钥匙都要交给一个人
生活中的类比
想象你是一个大楼的物业经理(root)。
- su命令: 相当于把你的 万能钥匙 交给别人——他拿到后可以开任何门。缺点是他必须知道你的密码。
- sudo命令: 相当于给每个员工一张 门禁卡,只能开指定的门。你不需要告诉他万能钥匙的密码,而且你可以随时收回他的门禁卡。
sudo的核心思想:分权管理,最小权限原则。
7.1 su vs sudo
| 对比项 | su | sudo |
|---|---|---|
| 切换方式 | 输入 root密码 | 输入 自己的密码 |
| 权限范围 | 完全获得root权限 | 只获得被授权的权限 |
| 安全性 | 低(需共享root密码) | 高(无需共享root密码) |
| 审计追踪 | 无法追踪谁在使用 | 有日志记录每次使用 |
| 推荐度 | 不推荐日常使用 | 推荐 |
7.2 配置sudo权限
问题: 如何让普通用户执行特定的管理命令,而无需root密码?
解答: 编辑 /etc/sudoers 文件,推荐使用 visudo 命令(它会进行语法检查,防止写错导致系统无法使用sudo)。
# 编辑sudoers文件(推荐方式,带语法检查)
visudo
# 或者直接编辑(不推荐,没有语法检查)
vim /etc/sudoers
sudoers规则语法
# 格式: 用户 主机=(以谁的身份运行) 可执行的命令
# user MACHINE=(RUNAS_USER) COMMANDS
# 示例1: 让robin可以在任何主机上以任何身份运行任何命令
robin ALL=(ALL) ALL
# 示例2: 让zorro可以执行网络和磁盘管理命令,且不需要密码
zorro ALL=(ALL) NOPASSWD: /sbin/ip, /sbin/fdisk
# 示例3: 让robin只能执行ip和fdisk命令
robin ALL=(ALL) /sbin/ip, /sbin/fdisk
# 示例4: 禁止执行某个命令(在命令前加!)
zorro ALL=(ALL) /usr/bin/passwd [a-zA-Z]*, !/usr/bin/passwd root
# 解释: zorro可以改普通用户的密码,但不能改root的密码
7.3 使用命令别名 -- 批量管理
当规则很多时,可以使用 别名(Alias) 来简化配置:
# ===== 在sudoers文件中定义别名 =====
# 命令别名: 把一组相关命令打包成一个别名
Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, \
/sbin/dhclient, /sbin/iptables, /sbin/iwconfig, /sbin/mii-tool
Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, \
/sbin/partprobe, /bin/mount, /bin/umount
Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, \
/usr/bin/systemctl start, /usr/bin/systemctl stop, \
/usr/bin/systemctl restart, /usr/bin/systemctl status, \
/usr/bin/systemctl enable, /usr/bin/systemctl disable
Cmnd_Alias USER = /usr/sbin/useradd, /usr/sbin/usermod, /usr/sbin/userdel, \
/usr/bin/passwd [a-zA-Z0-9]*, !/usr/bin/passwd root
Cmnd_Alias GROUP = /usr/sbin/groupadd, /usr/sbin/groupmod, /usr/sbin/groupdel
Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/yum, /usr/bin/dnf
# 用户别名: 把一组用户打包
User_Alias ADMINS = tom, jerry
User_Alias OPERATORS = alice, bob
# ===== 使用别名分配权限 =====
# 管理员可以管理网络、软件和服务
ADMINS ALL=(ALL) NETWORKING, SOFTWARE, SERVICES
# 运维人员可以管理用户、组和存储
OPERATORS ALL=(ALL) USER, GROUP, STORAGE
# 按组授权(%表示组名)
%developers ALL=(ALL) NOPASSWD: SERVICES
7.4 sudo安全最佳实践
# ===== 实用命令 =====
# 查看当前用户的sudo权限
sudo -l
# 以root身份执行命令
sudo /usr/sbin/useradd newuser
# 以其他用户身份执行命令
sudo -u apache /usr/bin/systemctl restart httpd
# 切换到root shell(需输入自己的密码)
sudo -i
sudo su -
# 查看sudo日志(审计谁在什么时候执行了什么命令)
tail -f /var/log/secure | grep sudo
# 强制要求输入密码(清除sudo缓存的密码)
sudo -k
安全建议清单:
- 最小权限原则: 只授权用户需要的具体命令,不要用
ALL - 使用visudo: 永远用
visudo编辑,避免语法错误 - 慎用NOPASSWD: 只在自动化脚本等场景使用,正常情况下应要求输入密码
- 禁止危险操作: 使用
!排除危险命令(如!/usr/bin/passwd root) - 定期审计: 检查
/var/log/secure中的sudo使用记录 - 避免ALL=(ALL) ALL: 除非真的需要完全root权限
课堂练习: 某学校服务器需要让张老师能管理用户(增删改用户、修改普通用户密码但不能改root密码),让李老师能管理网络和服务。请写出对应的sudoers配置。
8. SELinux -- 给系统穿上防弹衣
生活中的类比
假设你住在一栋安保严格的大楼里。
- 传统Linux权限(DAC): 就像你自己家——你是房主,想给谁钥匙就给谁。问题是你可能不小心给了坏人钥匙。
- SELinux(MAC): 就像大楼有一套 中央安保系统——即使你是房主,你也只能在安保系统允许的范围内行事。每个房间、每个人、每把钥匙都有标签(安全上下文),只有标签匹配才能访问。
即使黑客获得了root权限,如果SELinux策略不允许,他依然无法访问某些文件。
8.1 DAC vs MAC -- 两种安全模型
| 对比项 | DAC(自主访问控制) | MAC(强制访问控制) |
|---|---|---|
| 代表 | 传统Linux文件权限 (rwx) | SELinux |
| 权限决定者 | 文件所有者 | 系统策略(管理员不能随意更改) |
| 灵活性 | 高(所有者随意授权) | 低(由策略统一控制) |
| 安全性 | 较低(root可以为所欲为) | 高(即使root也受策略约束) |
| SUID风险 | 有(SUID程序漏洞可被利用) | 低(进程权限被严格限制) |
8.2 SELinux三种运行模式
# 查看当前模式
getenforce
# 输出: Enforcing / Permissive / Disabled
# 查看详细状态
sestatus
# 临时切换模式(Enforcing ↔ Permissive)
setenforce 0 # 切换到 Permissive(宽容模式:记录违规但不阻止)
setenforce 1 # 切换到 Enforcing(强制模式:阻止并记录)
| 模式 | 行为 | 适用场景 |
|---|---|---|
| Enforcing | 严格执行策略,阻止违规访问 | 生产环境 |
| Permissive | 记录违规但不阻止(相当于审计模式) | 调试排错 |
| Disabled | 完全关闭SELinux | 不推荐(除非兼容性问题) |
# 永久修改模式(需要重启)
vim /etc/selinux/config
# SELINUX=enforcing # 改为 enforcing / permissive / disabled
强烈建议: 不要关闭SELinux!如果遇到权限问题,先切到Permissive模式排查,而不是直接Disabled。
8.3 安全上下文(Security Context)
SELinux给每个文件、进程、端口都打上了 安全上下文标签。访问控制基于标签之间的匹配。
安全上下文格式: 用户:角色:类型:敏感度
示例:
system_u:object_r:httpd_sys_content_t:s0
^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^
用户 角色 类型(最重要!) 敏感度级别
| 组成部分 | 说明 | 常见值 |
|---|---|---|
| User | SELinux用户身份 | system_u, user_u, unconfined_u |
| Role | 角色 | object_r(文件), system_r(进程) |
| Type | 类型(核心!) | httpd_sys_content_t, etc_t, var_log_t |
| Sensitivity | 敏感度 | s0(默认,Target策略) |
关键点: SELinux的 类型强制(Type Enforcement) 是最核心的机制。规则可以简化为:
进程类型 能访问 文件类型,当且仅当策略中有明确的允许规则。
# 查看文件的安全上下文
ls -Z /var/www/html/
# 输出: system_u:object_r:httpd_sys_content_t:s0 index.html
# 查看进程的安全上下文
ps auxZ | grep httpd
# 输出: system_u:system_r:httpd_t:s0 1234 ? 00:00:00 httpd
# 查看端口的安全上下文
semanage port -l | grep http
8.4 修改文件安全上下文
问题: 我把网站文件放在了非默认目录 /web2 下,Apache报权限错误。
解答: Apache进程的类型是 httpd_t,它只能访问 httpd_sys_content_t 类型的文件。新目录的类型默认不是这个,需要手动修改。
# ===== 方法一:chcon(临时修改,不持久) =====
# 直接指定类型
chcon -R -t httpd_sys_content_t /web2
# 参考已有目录的类型
chcon -R --reference /var/www/html /web2
# ===== 方法二:semanage fcontext(推荐,持久化) =====
# 第一步:安装semanage工具
yum install -y policycoreutils-python
# 第二步:为目录添加默认文件上下文规则
semanage fcontext -a -t httpd_sys_content_t '/web2(/.*)?'
# 解释: '/web2(/.*)?' 是正则表达式,匹配/web2及其所有子文件
# 第三步:应用规则(恢复/设置文件的实际上下文)
restorecon -Rv /web2
# 验证
ls -Zd /web2
ls -Z /web2/
cp和mv对上下文的影响
# cp(复制):文件继承目标目录的上下文
cp /tmp/file1 /var/www/html/
# file1 获得 httpd_sys_content_t(正确!)
# mv(移动):文件保留原来的上下文!
mv /tmp/file2 /var/www/html/
# file2 仍然是 tmp_t(Apache无法访问!)
# 解决:移动后手动恢复上下文
restorecon -Rv /var/www/html/
8.5 SELinux布尔值 -- 策略开关
SELinux布尔值就像是策略的 开关,可以在不修改策略文件的情况下调整行为。
# 查看所有与httpd相关的布尔值
getsebool -a | grep httpd
# 查看特定布尔值
getsebool httpd_enable_homedirs
# 修改布尔值(临时)
setsebool httpd_enable_homedirs on
# 修改布尔值(永久,-P写入策略文件)
setsebool -P httpd_enable_homedirs on
# 或使用semanage查看(含持久性信息)
semanage boolean -l | grep httpd_enable_homedirs
常用布尔值:
| 布尔值 | 作用 |
|---|---|
| httpd_enable_homedirs | 允许Apache访问用户家目录 |
| httpd_can_network_connect | 允许Apache发起网络连接 |
| httpd_can_sendmail | 允许Apache发送邮件 |
| ftp_home_dir | 允许FTP访问用户家目录 |
| nis_enabled | 允许NIS服务 |
8.6 SELinux端口管理
问题: 我把Apache的监听端口改为8888,启动失败:Permission denied。
解答: SELinux限制了httpd进程只能绑定特定的端口。需要把新端口加入允许列表。
# 查看httpd允许的端口
semanage port -l | grep http_port_t
# 输出: http_port_t tcp 80, 443, 488, 8008, 8009, 8443
# 添加8888端口到httpd允许列表
semanage port -a -t http_port_t -p tcp 8888
# 验证
semanage port -l | grep http_port_t
# 输出: http_port_t tcp 8888, 80, 443, 488, 8008, 8009, 8443
# 现在可以正常启动Apache了
systemctl start httpd
8.7 SELinux故障排查流程
┌───────────────────────────────────────────────────┐
│ SELinux 故障排查四步法 │
│ │
│ 1. 确认是否是SELinux导致的问题 │
│ setenforce 0 ← 临时切到Permissive │
│ 如果问题解决 → 确认是SELinux的问题 │
│ setenforce 1 ← 切回Enforcing继续排查 │
│ │
│ 2. 安装排错工具 │
│ yum install -y setroubleshoot-server │
│ systemctl restart rsyslog │
│ systemctl restart auditd │
│ │
│ 3. 查看日志 │
│ grep "avc: denied" /var/log/audit/audit.log │
│ tail -f /var/log/messages | grep setroubleshoot│
│ │
│ 4. 根据日志修复 │
│ - 文件上下文不对 → restorecon / chcon / semanage│
│ - 端口不对 → semanage port │
│ - 需要开启布尔值 → setsebool -P │
│ │
└───────────────────────────────────────────────────┘
实战排错示例:
# 场景: Apache无法访问 /virtual/index.html
# 第一步:确认问题
setenforce 0
curl http://localhost/virtual/index.html # 能访问 → SELinux问题
setenforce 1
# 第二步:查看当前上下文
ls -Zd /virtual
# 输出: unconfined_u:object_r:default_t:s0 ← 类型是default_t,不是httpd能访问的
# 第三步:修复
semanage fcontext -a -t httpd_sys_content_t '/virtual(/.*)?'
restorecon -Rv /virtual
# 第四步:验证
ls -Zd /virtual
# 输出: system_u:object_r:httpd_sys_content_t:s0 ← 正确!
curl http://localhost/virtual/index.html # 能访问了
排错神器:
man -k selinux | grep http可以查看与Apache相关的SELinux帮助文档。
综合实验:构建安全的网络服务器
实验目标
在一台CentOS虚拟机上完成以下配置,综合运用本章所学知识:
| 序号 | 任务 | 涉及知识点 |
|---|---|---|
| 1 | 配置静态IP地址,划分子网 | IP地址、ip命令 |
| 2 | 配置firewalld,只开放SSH/HTTP/HTTPS | firewalld、区域、服务 |
| 3 | 部署Apache Web服务,使用自定义目录 | SELinux上下文、semanage |
| 4 | 配置sudo,让webadmin用户只能管理httpd服务 | sudoers、visudo |
| 5 | 抓包分析一次HTTP请求的完整过程 | TCP/IP、tcpdump |
| 6 | 配置OpenVPN,实现远程安全访问 | VPN、证书、加密 |
实验参考步骤
# 任务1: 配置IP
ip addr add 192.168.1.100/24 dev eth0
ip route add default via 192.168.1.1
# 任务2: 配置firewalld
systemctl start firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
# 任务3: 部署Apache + SELinux
yum install -y httpd
mkdir -p /myweb
echo "<h1>Hello World</h1>" > /myweb/index.html
semanage fcontext -a -t httpd_sys_content_t '/myweb(/.*)?'
restorecon -Rv /myweb
# 编辑/etc/httpd/conf/httpd.conf,设置DocumentRoot "/myweb"
systemctl start httpd
# 任务4: 配置sudo
visudo
# 添加: webadmin ALL=(ALL) /usr/bin/systemctl * httpd
# 任务5: 抓包分析
tcpdump -i eth0 -nn -S -w /tmp/http_capture.pcap port 80
# 另一台机器: curl http://192.168.1.100
# 用Wireshark打开/tmp/http_capture.pcap分析
附录:常用命令速查表
网络诊断
ip addr show # 查看IP地址
ip route show # 查看路由表
ip neigh show # 查看ARP缓存
ss -tunlp # 查看端口监听
ping -c 4 目标IP # 测试连通性
traceroute 目标IP # 追踪路由路径
nslookup 域名 # DNS解析
dig 域名 # 详细DNS查询
netstat -rn # 查看路由表
防火墙
# iptables
iptables -L -n -v --line-numbers
iptables -t nat -L -n -v
iptables-save > /etc/sysconfig/iptables
# firewalld
firewall-cmd --list-all
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
SELinux
getenforce # 查看模式
sestatus # 详细状态
ls -Z 文件 # 查看文件上下文
ps auxZ # 查看进程上下文
restorecon -Rv 目录 # 恢复默认上下文
semanage fcontext -l # 查看文件上下文规则
semanage port -l # 查看端口上下文
getsebool -a # 查看所有布尔值
安全加固
# SSH加固(/etc/ssh/sshd_config)
PermitRootLogin no # 禁止root直接登录
PasswordAuthentication no # 禁止密码登录,使用密钥
Port 2222 # 修改默认端口
# 系统更新
yum update -y # 更新所有软件包
# 检查可疑登录
last # 查看登录历史
lastb # 查看失败的登录尝试
术语表
| 术语 | 英文 | 解释 |
|---|---|---|
| IP地址 | IP Address | 网络中设备的唯一标识 |
| 子网掩码 | Subnet Mask | 区分IP中网络号和主机号的掩码 |
| CIDR | Classless Inter-Domain Routing | 无类别域间路由,如/24 |
| NAT | Network Address Translation | 网络地址转换 |
| TCP | Transmission Control Protocol | 传输控制协议(可靠) |
| UDP | User Datagram Protocol | 用户数据报协议(不可靠) |
| ARP | Address Resolution Protocol | 地址解析协议(IP→MAC) |
| ICMP | Internet Control Message Protocol | 互联网控制报文协议 |
| DNS | Domain Name System | 域名系统 |
| VPN | Virtual Private Network | 虚拟专用网络 |
| MITM | Man In The Middle | 中间人攻击 |
| SSL/TLS | Secure Sockets Layer / Transport Layer Security | 安全传输协议 |
| MAC | Mandatory Access Control | 强制访问控制 |
| DAC | Discretionary Access Control | 自主访问控制 |
| MTU | Maximum Transmission Unit | 最大传输单元(默认1500字节) |
| TTL | Time To Live | 生存时间(跳数限制) |
| MSS | Maximum Segment Size | 最大报文段长度 |
寄语: 网络安全和服务器管理是一门实践性很强的学科。理论只是基础,真正的能力来自于大量的动手练习。建议在实际操作中加深理解。遇到SELinux报错不要怕——把它当成解谜游戏,每一步排查都会让你对Linux的理解更深一层。