第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)