第8章 Netfilter与防火墙
学习目标
- 理解Netfilter框架和5个Hook点
- 掌握iptables和nftables的使用
- 了解连接跟踪(conntrack)机制
- 能够配置和排查防火墙规则
🔬 原理
Netfilter框架
5个Hook点:
PREROUTING → (路由决策) → FORWARD → POSTROUTING
↓ ↑
INPUT OUTPUT
↓ ↑
本机应用
Hook点说明:
- PREROUTING:包进入后,路由决策前
- INPUT:发往本机的包
- FORWARD:转发的包
- OUTPUT:本机发出的包
- POSTROUTING:路由决策后,发送前
iptables四表五链
四表:
- raw表:连接跟踪前处理
- mangle表:修改包头
- nat表:地址转换
- filter表:过滤决策(默认表)
五链:
- PREROUTING:raw、mangle、nat
- INPUT:mangle、filter
- FORWARD:mangle、filter
- OUTPUT:raw、mangle、nat、filter
- POSTROUTING:mangle、nat
连接跟踪(conntrack)
conntrack状态:
- NEW:新连接
- ESTABLISHED:已建立连接
- RELATED:相关连接
- INVALID:无效连接
conntrack表:
# 查看连接跟踪表
sudo conntrack -L
# 查看统计信息
sudo conntrack -S
️ 实现
Netfilter核心结构
struct nf_hook_ops {
struct list_head list;
nf_hookfn *hook; // Hook函数
struct module *owner; // 模块所有者
u_int8_t pf; // 协议族
unsigned int hooknum; // Hook点
int priority; // 优先级
};
struct nf_hook_state {
unsigned int hook; // Hook点
u_int8_t pf; // 协议族
struct net_device *in; // 输入设备
struct net_device *out; // 输出设备
struct sock *sk; // Socket
struct net *net; // 网络命名空间
int (*okfn)(struct net *, struct sock *, struct sk_buff *);
};
iptables实现
规则结构:
struct ipt_entry {
struct ipt_ip ip; // IP匹配
unsigned int nfcache; // 缓存标志
__u16 target_offset; // 目标偏移
__u16 next_offset; // 下一个规则偏移
unsigned int comefrom; // 来源
struct xt_counters counters; // 计数器
unsigned char elems[0]; // 扩展数据
};
🛠️ 命令
iptables命令
# 查看规则
sudo iptables -L -n -v
# 添加规则
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 删除规则
sudo iptables -D INPUT -p tcp --dport 22 -j ACCEPT
# 清空规则
sudo iptables -F
# 保存规则
sudo iptables-save > /etc/iptables/rules.v4
nftables命令
# 查看规则
sudo nft list ruleset
# 添加规则
sudo nft add rule inet filter input tcp dport 22 accept
# 删除规则
sudo nft delete rule inet filter input tcp dport 22 accept
# 清空规则
sudo nft flush ruleset
代码
简单防火墙程序
// simple_firewall.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
int main() {
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock < 0) {
perror("socket");
return 1;
}
char buffer[4096];
while (1) {
int len = recv(sock, buffer, sizeof(buffer), 0);
if (len < 0) {
perror("recv");
continue;
}
struct iphdr *ip = (struct iphdr*)buffer;
struct tcphdr *tcp = (struct tcphdr*)(buffer + (ip->ihl << 2));
// 简单的防火墙规则
if (tcp->dest == htons(22)) {
printf("Blocked SSH connection from %s:%d to %s:%d\n",
inet_ntoa(*(struct in_addr*)&ip->saddr),
ntohs(tcp->source),
inet_ntoa(*(struct in_addr*)&ip->daddr),
ntohs(tcp->dest));
}
}
close(sock);
return 0;
}
编译运行:
gcc simple_firewall.c -o simple_firewall
sudo ./simple_firewall
🧪 实验
实验1:iptables规则配置
目标:配置基本的防火墙规则
步骤:
# 1. 查看当前规则
sudo iptables -L -n -v
# 2. 清空规则
sudo iptables -F
# 3. 设置默认策略
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
# 4. 允许SSH
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 5. 允许已建立连接
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 6. 测试规则
telnet localhost 22
预期结果:
- 理解iptables规则配置
- 掌握防火墙策略设置
- 验证规则生效
实验2:NAT配置
目标:配置SNAT和DNAT
步骤:
# 1. 启用IP转发
sudo sysctl -w net.ipv4.ip_forward=1
# 2. 配置SNAT
sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE
# 3. 配置DNAT
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to 192.168.1.100:80
# 4. 查看NAT规则
sudo iptables -t nat -L -n -v
预期结果:
- 理解NAT工作原理
- 掌握SNAT和DNAT配置
- 验证地址转换
实验3:nftables配置
目标:使用nftables配置防火墙
步骤:
# 1. 创建表
sudo nft add table inet filter
# 2. 创建链
sudo nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'
# 3. 添加规则
sudo nft add rule inet filter input ct state established,related accept
sudo nft add rule inet filter input tcp dport 22 accept
# 4. 查看规则
sudo nft list ruleset
预期结果:
- 理解nftables语法
- 掌握nftables配置
- 对比iptables和nftables
排错
常见问题排查
问题1:规则不生效
# 检查规则顺序
sudo iptables -L -n -v --line-numbers
# 检查默认策略
sudo iptables -L -n
# 检查规则语法
sudo iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
问题2:连接被拒绝
# 检查INPUT链
sudo iptables -L INPUT -n -v
# 检查FORWARD链
sudo iptables -L FORWARD -n -v
# 检查NAT规则
sudo iptables -t nat -L -n -v
问题3:性能问题
# 检查规则数量
sudo iptables -L -n | wc -l
# 检查连接跟踪表
sudo conntrack -S
# 优化规则顺序
sudo iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
排错清单
- [ ] 检查规则语法(iptables -L -n)
- [ ] 验证规则顺序(--line-numbers)
- [ ] 确认默认策略(-P)
- [ ] 检查连接跟踪(conntrack -L)
- [ ] 测试规则生效(telnet、nc)
- [ ] 查看系统日志(dmesg、/var/log/syslog)
- [ ] 检查网络连通性(ping、traceroute)