惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
P
Privacy International News Feed
P
Proofpoint News Feed
Security Archives - TechRepublic
Security Archives - TechRepublic
C
CXSECURITY Database RSS Feed - CXSecurity.com
Know Your Adversary
Know Your Adversary
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Attack and Defense Labs
Attack and Defense Labs
NISL@THU
NISL@THU
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
GbyAI
GbyAI
N
News and Events Feed by Topic
N
News | PayPal Newsroom
Y
Y Combinator Blog
C
CERT Recently Published Vulnerability Notes
N
Netflix TechBlog - Medium
S
Security Affairs
Spread Privacy
Spread Privacy
罗磊的独立博客
腾讯CDC
MyScale Blog
MyScale Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
LINUX DO - 热门话题
The Cloudflare Blog
L
LangChain Blog
博客园_首页
H
Hacker News: Front Page
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
SecWiki News
SecWiki News
A
Arctic Wolf
爱范儿
爱范儿
Google Online Security Blog
Google Online Security Blog
T
Threat Research - Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
有赞技术团队
有赞技术团队
The GitHub Blog
The GitHub Blog
Cyberwarzone
Cyberwarzone
博客园 - 叶小钗
V
Visual Studio Blog
V
V2EX
T
Tailwind CSS Blog
Project Zero
Project Zero
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs
MongoDB | Blog
MongoDB | Blog
D
Docker

blog@real186526

随笔 Kiss me before I rise 辛德瑞拉。 不断忘记一切的我和接住我的你 —— 「今夜,即使这份爱恋从世上消散」 パレード (Parade 游行)—— 请不要忘记我孤身一人的盛装游行。 白鸟过河滩 Shut Up and Take My Card - 奇特的大陆银行卡外刷小 Tips 若存在终站之后。 雨声残响 八月、某、月明かり(八月、某地、月光皎明)—— My whole life was saved by Rock & Roll. 「花与麦芽糖,最终电车。」 漫谈中国支付系统和银行系统: 一些有意思的事实 重新开始 - 所以我尝试了一下 Hugo Cloudflare Free Argo tunnel 白嫖计划 「 Run short links service with aka 」- 如何部署aka 如何使用 debootstrap 构建一个最小化的Ubuntu Markdown Syntax Guide Math Typesetting
在 Linux Router 上配置 Source-Based Routing 策略(源进源出)
2026-01-10 · via blog@real186526

近期从朋友手里嫖了一点带宽,但是上游的网络配置明显禁止了非对称路由,所以按照我们 AS47778 的骨干设计来讲,内网的路由不对称,会导致有些并非来自该上游的来向包被选路到该上游出口。

所以,我们接下来基于 nftables 和 iproute2 来配置了 Source-Based Routing,来保证仅有来自该上游的包可以选择该上游进行转发。

Netfilter 和 nftables

Netfilter 是 Linux 内核中的一个用于管理数据包的框架。一切数据包都从 Netfilter 经过,经历如下图所示的周期。在 prerouting、input、output、forward 和 postrouting 阶段,Netfilter 允许 iptables 和 nftables 这样的应用程序对数据包进行控制,这也正是防火墙的基础。

Netfilter-packet-flow

看起来很麻烦吧,所以我们来简化一下。

1
2
3
4
5
(NETIN) -> PREROUTING -> <ROUTING> -> FOWARD -> POSTROUTING -> (NETOUT)
                             |                       ↑
                             |                   <ROUTING>
                             ↓                       ↑
                           INPUT   -> [LOCAL]  ->  OUTPUT

对于到本地的包 A,从 NETIN 进入之后,会通过 PREROUTING 链,到达 ROUTING 进行路由决策,检查到是本机包后进入 INPUT 链,然后被实际的发送给本地的程序。
本地的程序处理后,发送向外部的包 B,从 LOCAL 进入后到达 OUTPUT 链,再次到达 ROUTING 进行路由决策,通过 POSTROUTING 链后最终从 NETOUT 离开本机。

对于需要转发的包 C,从 NETIN 进入之后,通过 PREROUINTG 链,到达 ROUTING 进行路由决策,检查到需要转发,进入 FORWARD 链,通过 POSTROUTING 链后最终从 NETOUT 离开本机。

对于我们目前的情况而言,我们来分析以下不同包的情况:

  1. 去包从该上游进入网络内部,在本节点需要转发到网内的去包:正常转发。
  2. 去包从该上游进入网络内部,在本节点需要响应回包:回包正常按照选路离开节点或收到回包后源进源出即可。
  3. 去包从其他节点进入网络内部,在本节点需要继续转发在网内的去包:正常按照选路离开节点即可。
  4. 去包从其他节点进入网络内部,在本节点需要响应回包:回包不可以从该上游离开网络,需要源进源出。

在 Linux 的网络栈中,我们可以通过向包添加 fwmark (通常是一个 32bit 的无符号证书) 的方式来为数据包添加 tag,通过这个 tag 来在路由决策里将路由导向不同的 NETOUT。

同时也存在着一个 conntrack 机制和对应的 conntrack 表,用来追踪整个连接,通常被用于 NAT 环境中方便维护转发关系,我们在这里也会使用用来解决 2 的回包进行源进源出问题。

对于我们的场景而言,我们主要需要以上的 2 和 3 两个情况进行源进源出策略。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/usr/sbin/nft -f

table inet source_routing {
    chain prerouting {
        type filter hook prerouting priority mangle; policy accept;

        iifname "up1" ct mark set 0x00000001
        iifname "node1" ct mark set 0x00000002
        iifname "node2" ct mark set 0x00000003

        ct state {established, related} meta mark set ct mark
    }

    chain output {
        type route hook output priority mangle; policy accept;
        meta mark set ct mark
    }
}

我们在这里创建一个名为 source_routing 的表,同时为 IPv4 和 IPv6 应用 (inet)。

PREROUTING 链上,为来自不同接口的 packet 的连接打上了 ct mark,用来追踪连接。
对于已经被 ct mark 匹配并追踪的既有连接的包,我们直接将 ct mark 作为 fwmark 的值复制。
通过PREROUTING 链和 conntrack,我们给符合 2 条件的包打上了 fwmark。

OUTPUT 链上,是本地程序响应的包,符合 4 条件。我们直接 copy ct mark 到 fwmark。

iproute2、路由分表和策略路由

在 Linux 中,最多可以存在 255 (1-255) 个路由表,系统默认为我们配置 255 (local) / 254 (main) / 253 (default) 三个路由表。

local 表中包含本机路由和广播信息,127.0.0.1/8 的路由就来自该路由表,该表的内容由内核主动维护,理论来讲不需要额外的修改。

main 表中包含默认配置的路由信息,是默认使用工具添加的表格,正常的 ip route add 就会将路由添加到该表。

default 表默认内容为空,可以手动指明向该表写路由。

对于我们需求而言,我们需要创造 N 个表(N 即该节点的外联节点+上游个数),并给对应的表添加路由来。

在 Linux with iproute2,我们需要在 /etc/iproute2/rt_tables 维护表格配置。

1
2
3
4
5
6
7
8
9
255     local
254     main
253     default
0       unspec

# Following is what we modified.
100 up1_table
101 node1_table
102 node2_table

我们在这里添加了 100 101 102 三个表,分别 mapping 到 up1_table node1_table node2_table 上。

对于我们的要求,可以直接添加 default via $gateway dev $device 到各个路由上。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/bin/bash
# policy.sh
export src="fe80::2" # 通过该变量来保证不同 interface 上出包 src 的 IP 一致。

while IFS='|' read -r fwmark device table gateway; do
    fwmark=$(echo "$fwmark" | tr -d '[:space:]')
    device=$(echo "$device" | tr -d '[:space:]')
    table=$(echo "$table" | tr -d '[:space:]')
    gateway=$(echo "$gateway" | tr -d '[:space:]')

    sudo ip route add default via "$gateway" dev "$device" src "$src" table "$table"
    sudo ip rule add fwmark "$fwmark" lookup "$table"
done
1
2
3
4
5
# policy.conf
# fwmark|device|table|gateway
0x1|up1|up1_table|fe80::1
0x2|node1|node1_table|fe80::1
0x3|node2|node2_table|fe80::1
1
cat policy.conf | sudo policy.sh

通过这个小脚本,我们分别给每个表都按照配置加入了对应的到 gateway 的默认路由,然后配置了包含 fwmark 的包都按照对应的 fwmark 命中到表上。

此时对于来自该上游并需要在本地响应的回包:

  1. 入包命中 PREROUTING 链,并被打上 ct mark
  2. 回包进入 OUTPUT 链,将 ct mark 复制到 fwmark 上
  3. 回包进入 ROUTING 路由决策,匹配 fwmark 到对应的仅默认路由路由表上
  4. 回包离开本机

以上,我们成功配置了源进源出的网络路由方案,顺带对 fwmark 和 nftables 等有了初步的了解。若要进一步了解 nftables 及其配置, 官方 wiki 是个不错的选择,无论是配置过程中遇到问题还是希望进行更复杂的配置,都能在官方 wiki 找到详尽的说明。总之,配网愉快~