瑞克
Published on 2026-07-16 / 0 Visits
0
0

防火墙与安全

防火墙与安全——给服务器装上"防盗门"和"监控摄像头"

导读:如果服务器是你家,那防火墙就是"防盗门+保安"——决定谁能进来、谁要被拦在外面。而安全配置(sudo、SELinux)就像家里的"权限系统"——保姆只能进厨房,客人只能坐客厅,只有房主才能进保险柜房间。本章我们就来学习如何全方位保护服务器安全!


一、iptables——Linux经典防火墙

1.1 为什么需要防火墙?

问题场景:你的服务器暴露在公网上,有22(SSH)、80(HTTP)、3306(MySQL)等多个端口开放。如果不加限制,任何人都可以尝试连接这些端口——黑客可能会暴力破解SSH密码,或者直接攻击数据库。

解决方案:配置防火墙规则,只允许合法的流量通过,把可疑流量挡在外面。

生活类比:防火墙 = 小区门卫。门卫手里有一张"访客白名单"——只有名单上的人才能进小区,其他人一律拦截。

1.2 四表五链——iptables的核心架构

iptables不是简单的"允许/拒绝"列表,它有一套完整的规则处理框架:

四张表(Table)——按功能分类:

表名功能类比
filter过滤数据包(允许/拒绝)保安检查进出人员
nat网络地址转换前台转接电话
mangle修改数据包的特定字段给包裹贴特殊标签
raw在连接追踪之前处理数据包快递站初筛

五条链(Chain)——按数据流向分类:

链名数据流方向类比
PREROUTING数据包刚到达,还没路由决策小区大门入口
INPUT发往本机的数据包送到你家门口
FORWARD经过本机转发的数据包穿过小区去别的地方
OUTPUT本机发出的数据包你出门去别处
POSTROUTING数据包即将离开本机小区大门出口

数据包处理流程

外部数据包到达
      |
      v
 PREROUTING链 (raw -> mangle -> nat)
      |
      v
  路由决策:目标是本机?还是转发?
      |                    |
      v                    v
  INPUT链              FORWARD链
 (filter -> mangle)   (mangle -> filter)
      |                    |
      v                    v
  本机进程              POSTROUTING链
      |               (mangle -> nat)
      v                    |
  OUTPUT链                 v
(raw -> mangle ->      数据包离开
 nat -> filter)

1.3 iptables基本操作

安装与管理

操作RHEL系(CentOS/Rocky)Debian系(Ubuntu)
安装yum install iptables iptables-servicesapt install iptables
启动systemctl start iptables默认已安装,无service
开机自启systemctl enable iptablesapt install iptables-persistent
查看规则iptables -L -n --line-numbers同左
保存规则service iptables saveiptables-save > /etc/sysconfig/iptablesnetfilter-persistent save

常用参数详解

参数含义示例
-A在链末尾追加规则iptables -A INPUT -p tcp --dport 22 -j ACCEPT
-I在链头部(或指定位置)插入规则iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
-D删除规则iptables -D INPUT 3(删除第3条)
-P设置链的默认策略iptables -P INPUT DROP
-F清空链中所有规则iptables -F INPUT
-j指定匹配后的动作ACCEPT / DROP / REJECT

三种动作的区别

动作效果类比
ACCEPT允许通过保安放行
DROP直接丢弃,不回复保安假装没看见你
REJECT拒绝并回复"拒绝"消息保安告诉你"不让进"

1.4 iptables实战配置

场景:配置一台Web服务器的防火墙

iptables -F                                      # 清空规则
iptables -P INPUT DROP                            # 默认拒绝入站
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT                         # 出站允许
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT  # 已建立的连接
iptables -A INPUT -i lo -j ACCEPT                 # 回环接口
iptables -A INPUT -p tcp --dport 22 -j ACCEPT     # SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT     # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT    # HTTPS
iptables -A INPUT -p icmp -j ACCEPT               # ping

# 保存规则
# RHEL: service iptables save
# Debian: netfilter-persistent save

互动提问:如果忘了加第三步(允许ESTABLISHED连接),会发生什么?
(答:你已经SSH连上了,但服务器的回复包会被DROP规则拦截,SSH连接会断开!)

1.5 NAT端口转发实战

SNAT(源地址转换)——让内网服务器通过公网IP上网:

# 让192.168.1.0/24网段通过eth0的公网IP上网
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 公网IP

# 如果公网IP是动态的,使用MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

DNAT(目标地址转换)——把公网端口的流量转发到内网服务器:

# 把公网IP的80端口转发到内网192.168.1.100的80端口
iptables -t nat -A PREROUTING -d 公网IP -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80

# 同时需要开启IP转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效:
# 编辑 /etc/sysctl.conf,设置 net.ipv4.ip_forward = 1
sysctl -p

生活类比

  • SNAT = 公司所有人用同一个总机号码打外线(对外显示同一个号码)
  • DNAT = 外面打进来的总机电话,前台帮你转接到具体分机

二、firewalld——新一代动态防火墙

2.1 为什么需要firewalld?

问题场景:iptables每次修改规则都需要重载所有规则,在规则很多时会短暂中断网络连接。而且iptables配置文件是纯命令堆积,不够直观。

解决方案:firewalld支持动态修改规则,不需要重载整个防火墙;用"区域"(zone)的概念让管理更直观。

2.2 区域(Zone)概念

生活类比:区域就像"安全等级不同的区域"——

  • 公共区域(public)= 大马路上,谁都能经过,最严格
  • 工作区域(work)= 公司大楼,员工可进,较信任
  • 家庭区域(home)= 家里,家人都能进,很信任
  • 可信区域(trusted)= 自己的房间,完全信任

默认区域列表

区域信任级别典型用途
drop最低,丢弃所有入站极端安全场景
block拒绝所有入站(回复reject)高安全需求
public不信任任何入站(默认)公网服务器
external外部网络,启用伪装路由器外网口
dmz只允许选定的入站DMZ隔离区
work信任大部分入站公司内网
home信任大部分入站家庭网络
internal信任内部网络内网服务器
trusted信任所有仅测试用

2.3 firewalld基本操作

安装与管理

操作RHEL系Debian系
安装yum install firewalld(默认已装)apt install firewalld
启动systemctl start firewalldsystemctl start firewalld
开机自启systemctl enable firewalldsystemctl enable firewalld
状态systemctl status firewalldsystemctl status firewalld

firewall-cmd常用命令

# === 基本操作 ===
firewall-cmd --state                          # 查看防火墙状态
firewall-cmd --get-default-zone               # 查看默认区域
firewall-cmd --get-active-zones               # 查看活跃区域
firewall-cmd --reload                         # 重载配置(不中断连接)
firewall-cmd --complete-reload                # 完全重载(会中断连接)

# === 服务管理 ===
firewall-cmd --list-all                       # 查看当前区域所有规则
firewall-cmd --list-services                  # 查看已开放的服务
firewall-cmd --add-service=http               # 临时开放HTTP服务
firewall-cmd --add-service=http --permanent   # 永久开放HTTP服务
firewall-cmd --add-service=https --permanent  # 永久开放HTTPS服务
firewall-cmd --remove-service=smtp --permanent # 永久移除SMTP服务

# === 端口管理 ===
firewall-cmd --add-port=8080/tcp --permanent  # 永久开放8080端口
firewall-cmd --add-port=3306/tcp              # 临时开放3306端口
firewall-cmd --remove-port=23/tcp --permanent  # 永久关闭Telnet端口
firewall-cmd --list-ports                     # 查看已开放的端口

# === 富规则(Rich Rules)===
# 只允许特定IP访问SSH
firewall-cmd --add-rich-rule='rule family="ipv4" source address="10.0.0.0/24" service name="ssh" accept' --permanent

# 拒绝特定IP的所有访问
firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.100" drop' --permanent

# 限制SSH连接速率(每分钟最多3次)
firewall-cmd --add-rich-rule='rule service name="ssh" limit value="3/m" accept' --permanent

# 查看富规则
firewall-cmd --list-rich-rules

# === 地址伪装(Masquerade)===
firewall-cmd --add-masquerade --permanent     # 启用地址伪装(类似SNAT)
firewall-cmd --query-masquerade               # 查看是否启用

# === 端口转发(类似DNAT)===
# 把本机80端口的流量转发到8080端口
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080 --permanent

# 把本机80端口转发到另一台机器的8080端口
firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.1.100 --permanent

# 查看所有转发规则
firewall-cmd --list-forward-ports

注意:带 --permanent 的规则永久生效但不会立即生效,需要 firewall-cmd --reload 使其生效;不带 --permanent 的规则立即生效但重启后失效。

最佳实践:先加 --permanent,再执行 --reload

2.4 firewalld实战:配置Web服务器

firewall-cmd --set-default-zone=public
firewall-cmd --add-service=ssh --permanent
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --add-port=8080/tcp --permanent       # Tomcat端口
firewall-cmd --reload
firewall-cmd --list-all                            # 验证

三、iptables vs firewalld 对比

特性iptablesfirewalld
管理方式静态,修改后需全部重载动态,可热更新规则
配置文件/etc/sysconfig/iptables/etc/firewalld/ 目录下XML文件
命令行iptablesfirewall-cmd
概念模型表+链区域(Zone)
规则持久化需要手动保存--permanent + --reload
默认发行版较旧版本默认CentOS 7+/RHEL 8+/Fedora
学习曲线较低(命令直观)较高(区域概念多)
共存不能与firewalld同时运行不能与iptables service同时运行

互动提问:如果你在一台CentOS 8服务器上,发现防火墙规则不生效,最可能是什么原因?
(答:可能firewalld和iptables-service冲突了,需要确认只运行其中一个。CentOS 8默认使用firewalld。)


四、VPN——虚拟专用网络

4.1 为什么需要VPN?

问题场景:小明在咖啡厅用公共WiFi办公,要访问公司内网的管理系统。公共WiFi不安全,数据可能被窃取。

解决方案:通过VPN建立一条加密的"隧道",所有数据都在这条隧道里传输,即使被截获也无法解密。

生活类比:VPN = 防弹运钞车。你的数据被装进装甲车(加密),走专用通道(隧道),外面的劫匪(黑客)就算看到车也不知道里面装的是什么。

4.2 VPN核心概念

概念说明
隧道(Tunnel)在公共网络上建立的虚拟专用通道
加密(Encryption)对传输数据进行加密,防止被窃取
认证(Authentication)验证连接双方的身份
封装(Encapsulation)把原始数据包包裹在新的数据包里传输

4.3 常见VPN协议对比

协议安全性速度适用场景
PPTP低(已不安全)不推荐使用
OpenVPN通用,开源免费
WireGuard新一代首选
IPSec/IKEv2移动端优选

建议:新项目推荐 WireGuard,配置简单、性能优秀、代码量少。

4.4 WireGuard快速体验

# RHEL: yum install wireguard-tools  |  Debian: apt install wireguard
# 生成密钥对
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey

五、中间人攻击(MITM)

5.1 什么是中间人攻击?

问题场景:小明连接了咖啡厅的WiFi,登录网银时,输入的密码被旁边一个"隐形人"截获了。

攻击原理:攻击者在通信双方之间"插入"自己,冒充服务器接收客户端数据,再冒充客户端发给服务器——双方都不知道中间有人在偷听。

生活类比:你给同桌传纸条,中间被另一个人截获了,他看完后又传给同桌。你俩都以为纸条是直达的,但其实被第三个人看过了。

5.2 ARP欺骗原理

在局域网中,ARP欺骗是最常见的MITM手段:

正常情况:
小明(192.168.1.2) ----ARP查询----> 网关(192.168.1.1)
                    <---回复MAC_G---

攻击情况:
攻击者(192.168.1.99) 伪造ARP回复给小明:
  "我是192.168.1.1,我的MAC是攻击者的MAC!"
小明信以为真,把本该发给网关的数据发给了攻击者
攻击者再把数据转发给真正的网关(小明毫无察觉)

5.3 防御ARP欺骗

# 方法1:设置静态ARP绑定(适合小型网络)
arp -s 192.168.1.1 AA:BB:CC:DD:EE:FF    # 绑定网关的真实MAC

# 方法2:使用ARP防护工具
# RHEL系
yum install arpwatch
systemctl start arpwatch

# Debian系
apt install arpwatch
systemctl start arpwatch

5.4 HTTPS如何防止MITM

HTTPS通过TLS证书机制防止中间人攻击:服务器发送CA签名的证书,客户端验证证书合法性后用公钥协商会话密钥,后续通信全部加密。攻击者无法伪造CA签名的证书。

安全提醒:浏览器弹出"此连接不安全"的警告时,绝对不要点"继续访问"!这很可能就是MITM攻击。


六、sudo权限管理

6.1 为什么需要sudo?

问题场景:公司有3个运维人员,都需要执行一些管理员操作(重启服务、查看日志),但不应该给他们root密码——万一有人误操作或离职了呢?

解决方案:sudo允许普通用户以root(或指定用户)的权限执行特定命令,而且有完整的审计日志。

生活类比:sudo = 公司钥匙管理系统。每个员工只能拿到自己需要打开的房间钥匙(权限),而且每次取钥匙都有记录(审计日志)。

6.2 配置sudo

编辑sudoers文件(必须用visudo命令,它会检查语法正确性):

# 编辑sudoers(默认使用vi编辑器)
visudo

# 如果习惯用nano
EDITOR=nano visudo

sudoers配置语法

用户  主机=(以谁的身份)  命令列表

常见配置示例

# 允许webadmin执行nginx相关命令
webadmin  ALL=(root)  /usr/sbin/nginx, /usr/bin/systemctl restart nginx

# 允许devops组执行所有命令(需密码)
%devops   ALL=(ALL)  ALL

# 允许backup用户免密执行rsync
backup    ALL=(root)  NOPASSWD: /usr/bin/rsync

6.3 sudo使用与安全实践

# 以root身份执行命令
sudo systemctl restart nginx

# 以指定用户身份执行
sudo -u postgres psql

# 查看当前用户的sudo权限
sudo -l

# 查看sudo审计日志
# RHEL系
grep sudo /var/log/secure
# Debian系
grep sudo /var/log/auth.log

# 切换到root(保持环境变量)
sudo -i
# 或
sudo su -

安全最佳实践

实践原因
最小权限原则只授予必要的命令权限
禁止NOPASSWD: ALL等于直接给了root密码
定期审计sudoers删除离职人员的权限
使用用户组管理用 %group 而非逐个用户配置
记录所有sudo操作确保可追溯

互动提问:如果给一个用户配置了 NOPASSWD: /bin/bash,这安全吗?
(答:极度不安全!这等于允许用户无密码启动一个root shell,等于完全root权限。)


七、SELinux——强制访问控制

7.1 为什么需要SELinux?

问题场景:即使你的防火墙和sudo都配好了,如果一个Web应用(如Nginx)存在漏洞被攻破,黑客可以以Nginx进程的身份读取系统上的敏感文件。

解决方案:SELinux提供强制访问控制(MAC)——即使进程被攻破,也只能访问被明确允许的资源。

生活类比:普通Linux权限 = 你有房间钥匙就能进任何房间。SELinux = 就算你有钥匙,但如果你是"保洁员"身份,系统只让你进厨房和卫生间,保险柜房间根本进不去。

7.2 SELinux三种模式

模式说明用途
Enforcing强制执行策略,违规即拒绝生产环境(推荐)
Permissive不阻止,只记录违规行为调试排障
Disabled完全关闭不推荐
# 查看当前模式
getenforce
# 或
sestatus

# 临时切换模式(重启后失效)
setenforce 0    # 切换到Permissive
setenforce 1    # 切换到Enforcing

永久修改模式

# 编辑配置文件
vi /etc/selinux/config

# 修改为:
# SELINUX=enforcing    # 强制模式(推荐)
# SELINUX=permissive   # 宽容模式(调试用)
# SELINUX=disabled     # 关闭(不推荐)

# 重启生效
reboot

7.3 SELinux安全上下文

SELinux给每个文件和进程都贴上"安全标签"(上下文):

# 查看文件的安全上下文
ls -Z /var/www/html/index.html
# 输出示例:system_u:object_r:httpd_sys_content_t:s0 /var/www/html/index.html

# 查看进程的安全上下文
ps auxZ | grep nginx

上下文格式:用户:角色:类型:级别

最重要的部分是类型(type)

  • httpd_sys_content_t:Web服务器可读的内容
  • httpd_sys_rw_content_t:Web服务器可读写的
  • etc_t:配置文件类型

7.4 SELinux常见问题与排障

场景:Nginx无法访问新创建的网页目录

# 问题:把网站文件放在 /opt/myweb/ 下,Nginx报403错误
# 原因:/opt/myweb/ 的文件类型不是 httpd_sys_content_t

# 诊断:
ls -Z /opt/myweb/
# 输出可能是:unconfined_u:object_r:usr_t:s0(不是Web类型)

# 解决方法1:修改文件上下文
chcon -R -t httpd_sys_content_t /opt/myweb/

# 解决方法2(推荐):定义持久化规则
semanage fcontext -a -t httpd_sys_content_t "/opt/myweb(/.*)?"
restorecon -Rv /opt/myweb/

# 解决方法3:使用SELinux布尔值
# 查看相关布尔值
getsebool -a | grep httpd
# 允许httpd访问用户主目录
setsebool -P httpd_read_user_content 1

常用SELinux排障命令

# 查看SELinux拒绝日志
# RHEL系
grep "denied" /var/log/audit/audit.log
# 或使用sealert(需安装setroubleshoot)
sealert -a /var/log/audit/audit.log

# Debian系(如果使用SELinux)
grep "denied" /var/log/audit/audit.log

# 使用ausearch查看审计日志
ausearch -m avc -ts recent

# 恢复文件默认安全上下文
restorecon -Rv /var/www/html/

chcon vs semanage vs restorecon

命令作用持久性
chcon临时修改文件安全上下文不持久(restorecon后失效)
semanage fcontext永久定义安全上下文规则持久(写入策略)
restorecon根据规则恢复文件的安全上下文持久(按规则重置)

互动提问:很多人一遇到SELinux问题就直接关闭它(setenforce 0),这有什么风险?
(答:关闭SELinux后,所有进程都失去了强制访问控制的保护,一旦某个服务被攻破,攻击者可以访问更多系统资源。正确做法是排查并修复策略。)


八、各发行版防火墙默认状态对比

发行版默认防火墙默认状态管理命令
CentOS 7firewalld启用firewall-cmd
CentOS 8/Streamfirewalld启用firewall-cmd
Rocky Linux 8/9firewalld启用firewall-cmd
RHEL 7/8/9firewalld启用firewall-cmd
Ubuntu 18.04+ufw禁用ufw
Ubuntu 22.04+ufw禁用ufw
Debian 10+nftables(底层)无默认前端nft
openSUSEfirewalld启用firewall-cmd

Ubuntu的UFW快速入门

# 启用ufw
ufw enable

# 开放SSH
ufw allow ssh
# 或
ufw allow 22/tcp

# 开放HTTP/HTTPS
ufw allow http
ufw allow https

# 查看状态
ufw status verbose

# 拒绝某个IP
ufw deny from 192.168.1.100

# 删除规则
ufw delete allow 8080/tcp

九、安全加固综合实战

9.1 服务器安全加固清单

# 1. 更新系统
# RHEL: yum update -y  |  Debian: apt update && apt upgrade -y

# 2. 禁用root远程SSH登录(编辑 /etc/ssh/sshd_config)
# PermitRootLogin no

# 3. 修改SSH默认端口
# Port 2222

# 4. 使用密钥认证,禁用密码登录
# PasswordAuthentication no

# 5. 配置防火墙(只开放必要端口)
firewall-cmd --add-service=ssh --permanent
firewall-cmd --add-service=http --permanent
firewall-cmd --add-service=https --permanent
firewall-cmd --reload

# 6. 安装fail2ban(防暴力破解)
# RHEL: yum install epel-release -y && yum install fail2ban -y
# Debian: apt install fail2ban -y
systemctl enable --now fail2ban

# 7. 启用SELinux(RHEL系)
setenforce 1

附录A:运维常用命令精选

命令用途示例
iptables -L -n查看iptables规则iptables -L INPUT -n --line-numbers
firewall-cmd --list-all查看firewalld所有规则firewall-cmd --list-all
ufw status查看UFW状态(Ubuntu)ufw status verbose
getenforce查看SELinux模式getenforce
sestatus查看SELinux详细状态sestatus
visudo安全编辑sudoersvisudo
sudo -l查看当前用户sudo权限sudo -l
grep "denied" /var/log/audit/audit.log查看SELinux拒绝日志ausearch -m avc -ts today
chcon修改文件安全上下文chcon -R -t httpd_sys_content_t /web
restorecon恢复默认安全上下文restorecon -Rv /var/www/
semanage fcontext持久定义安全上下文规则semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
getsebool -a查看SELinux布尔值`getsebool -a
fail2ban-client status查看fail2ban状态fail2ban-client status sshd
lastb查看失败的登录记录`lastb
last查看成功的登录记录`last

附录B:趣味命令

# 1. 看看谁在试图暴力破解你的服务器(触目惊心!)
# RHEL系
grep "Failed password" /var/log/secure | awk '{print $11}' | sort | uniq -c | sort -rn | head
# Debian系
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head

# 2. 实时观看谁在尝试登录你的服务器
# RHEL系
tail -f /var/log/secure | grep "Failed"
# Debian系
tail -f /var/log/auth.log | grep "Failed"

# 3. 查看当前所有活跃的TCP连接及来源IP
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head

# 4. 一键查看服务器上有多少个SYN_RECV(半连接)状态
# (如果有大量半连接,可能正遭受SYN Flood攻击)
ss -tn state syn-recv | wc -l

# 5. 查看防火墙规则总数(看看你的服务器有多"严防死守")
iptables -L -n | grep -c "^"

# 6. 快速检测某个端口是否对外开放
nmap -p 80,443,22 你的公网IP

# 7. 用tcpdump抓包看实时流量(需要root权限)
# 只看来自某个IP的流量
tcpdump -i eth0 -n host 192.168.1.100

# 8. 生成一个安全的随机密码(用于sudo用户)
openssl rand -base64 18

# 9. 查看系统最近的安全事件摘要
# RHEL系
aureport --summary
# 如果aureport不可用:
cat /var/log/secure | grep -E "sudo|su|login" | tail -30

# 10. 看看你的SELinux到底拦了多少次操作
grep "denied" /var/log/audit/audit.log | wc -l

小结:防火墙是服务器的第一道防线,sudo是权限管理的核心工具,SELinux提供深层的强制访问控制,VPN保护远程通信安全,而HTTPS则是防止中间人攻击的利器。安全是一个持续的过程——没有绝对安全的系统,只有不断提高的攻击成本。下一章我们将学习Web服务器的部署!


Comment