资讯动态

ifconfig手搓sit隧道:老服务器IPv6接入实战与排障

发布时间:2026/10/19 9:15:36 来源:尧图企业网站定制
上周处理一个服务器接入IPv6的需求时又撞上了 sit 隧道这档子事。机器是一台跑了好几年的老系统没装 iproute2网络管理工具链还是最传统的那套 net-tools所有运维脚本也都基于 ifconfig 在写。业务方要求这台机器必须能访问纯 IPv6 网段而物理网络只分配了 IPv4 地址所以只能用 ifconfig 手工创建一条 sit 隧道把 IPv6 流量接进来。原以为几分钟能搞定结果翻资料时发现一个尴尬现象现在的教程几乎全是ip tunnel add mode sit的写法纯 ifconfig 建 sit 隧道的资料又少又碎命令参数还经常踩坑。我把整个操作过程、原理拆解和排错经历整理成这篇文章给需要接手旧系统、或者想在最小化环境下手搓 IPv6 隧道的朋友做个参考。1. 先搞清楚sit 隧道到底在解决什么问题1.1 没有 IPv6 地址的机器怎么连上 IPv6 世界在理解 sit 隧道之前先明确一个场景很多物理机器、虚拟机、或者某些内部 IDC 机房的服务器IPv4 网络是正常的但 IPv6 还没有真正打通。要么是机房没分配 IPv6 地址段要么是交换机设备配置还没跟上。可偏偏现在不少外部服务、监控系统、数据同步接口都迁到了 IPv6-only 网络业务方要求你必须能访问这些资源。这时候最直接的思路不是去催网络管理员而是用“隧道”技术把 IPv6 报文装进 IPv4 报文里送出去到了对端再剥掉 IPv4 头还原成 IPv6 报文。这就是 IPv6-over-IPv4 封装的核心逻辑。sit 这个名字全称是 Simple Internet Transition正是 Linux 内核里实现这种 6-in-4 静态隧道的一种模式。它把完整的 IPv6 包当作 IPv4 包的 payload外层 IPv4 头的协议字段固定设为 41IPv6-in-IPv4 encapsulation对端收到后根据协议号 41 把负载交给 IPv6 协议栈处理。整个过程对外表现为 IPv4 流量但对内部 IPv6 网络来说就像多了一条“虚拟网线”。打个比方你有一辆只能在中国公路IPv4上跑的卡车现在要把一批货物送到只有高速公路IPv6能通的地方。sit 隧道就是给货物加了第二层包装卡车在中国公路上跑到了对端换一辆车再把货物放到高速公路上继续送。你真正关心的是货物的最终目的地而中间卡车走哪条路、怎么换装都是由隧道协议处理的。1.2 sit / GRE / IPIP 隧道差别没你想的那么小很多人会把 sit 和 GRE、IPIP 混在一起觉得都是“包一层头”的隧道技术实际上每种模式都有自己的定位和限制。隧道模式承载内容外层协议典型设备名用途IPIPIPv4 报文IPv4协议号 4tunl0IPv4-over-IPv4纯 IPv4 环境组网GRE多种三层协议IPv4 或 IPv6协议号 47gre0 / gre1通用封装支持 IPv4、IPv6、组播SITIPv6 报文IPv4协议号 41sit0 / sit1IPv6-over-IPv4 静态隧道IPIP 只能装 IPv4 报文功能单一但开销最小GRE 多了一个 GRE 头支持多协议承载灵活性最高sit 是专门为 IPv6 过渡设计的只承载 IPv6 报文。很多人误以为 sit 也能跑 IPv4实际上它内部只认 IPv6如果你打算用 sit 在 IPv4 网络之间封装 IPv4 流量那方向就错了。在 Linux 里sit 隧道由内核模块实现设备枚举为 sit0 和 sit1。sit0 是系统自带的模板设备不能直接当实际隧道用真正的隧道需要手动创建出来。这个就是后面实操里最容易卡住的地方。2. 为什么绕不开 ifconfig 这种老命令2.1 net-tools 和 iproute2 的旧账ifconfig 属于 net-tools 工具包底层通过 ioctl 系统调用和内核网络设备通信ip 命令属于 iproute2走的是 netlink 套接字。从功能角度看iproute2 明显更现代、表达能力更强但在某些老发行版、最小化安装镜像或者长期没有升级的服务器上net-tools 依然是预装工具ip 命令反而可能没装。现实运维环境里还有一种情况已有的自动化脚本全是 ifconfig route 的老语法几百行脚本不可能一夜之间改成 ip 命令。这时候你只能顺着现状用 ifconfig 去实现原来 ip 命令轻松完成的功能。这就是我现在还在写这篇文章的原因——不是 ifconfig 好用而是它依然存在于大量生产环境里。ifconfig 对 sit 隧道的支持其实一直很弱只有tunnel这一组参数不能精细指定本地地址、远端地址、TTL 这些属性更不能设置隧道密钥。它能做的只是把隧道“拉起来”配一个链路地址然后手动上静态路由。配置能力iproute2net-tools ifconfig指定本地 IPv4 源地址ip tunnel add local 支持不支持自动选路由地址指定远端 IPv4 地址ip tunnel add remote 支持ifconfig sit1 tunnel 支持设置 TTLip tunnel add ttl 支持不支持设置隧道密钥ip tunnel add key 支持不支持添加 IPv6 地址ip -6 addr add 支持ifconfig sit1 inet6 add 支持这张表说明了问题的本质ifconfig 能建隧道但建出来的隧道只能走最简单的静态模式。如果你的网络环境复杂、需要多隧道并存别指望它老老实实上 iproute2 或者直接改用 systemd-networkd。2.2 ifconfig 建 sit 隧道的几个反直觉写法用 ifconfig 操作 sit 隧道时有几个语法细节和现代工具的习惯完全不一样第一次用很容易懵。第一个是sit0和sit1的区别。内核一加载 sit 模块自动就会出现 sit0很多人以为直接ifconfig sit0 up再配地址就能用结果发现这个接口看起来是 up 的但流量根本过不去。因为 sit0 只是一个“模板设备”它存在的意义是让内核知道有 sit 隧道这个链路层类型真正收发数据必须基于它创建具体的隧道接口比如 sit1。创建之后sit1 才是有实际封装参数的虚拟设备。第二个是tunnel参数的地址写法。ifconfig 支持直接把 IPv4 点分地址传给 tunnel 参数比如ifconfig sit1 tunnel 203.0.113.2这行命令底层会把 IPv4 地址转换成 IPv4-mapped IPv6 地址格式存入隧道参数。有些文档里会写tunnel ::203.0.113.2也是等价的只是形式不同。第三个需要注意的坑是“必须先配置远端地址再配置 IPv6 链路地址”。如果你先给 sit1 配上 IPv6 地址再指定 tunnel 对端地址部分版本的内核会把隧道接口重置导致 IPv6 地址丢失。我实际操作时也踩过这个顺序坑后来固定了一套顺序create - tunnel - inet6 add - mtu - up一路执行下来没再出过问题。3. 一步步把 sit 隧道跑起来3.1 动手前的环境检查和拓扑约定为了让整个操作过程可复现我先定一个最典型的双机拓扑。本端服务器 A 的公网 IPv4 地址是 203.0.113.1文档保留地址仅作演示对端服务器 B 的公网 IPv4 地址是 203.0.113.2。A 需要访问 B 后侧的 IPv6 网段 2001:db8:2::/64隧道两端各配一个链路本地地址和点对点地址A 隧道接口2001:db8:1::2/64B 隧道接口2001:db8:1::1/64B 后侧目标网段2001:db8:2::/64操作前先确认内核支持 sit 模块。执行modprobe sit没有报错就是加载成功再查一下设备是否存在modprobe sit ls /sys/module/sit如果执行 modprobe 时提示找不到模块说明内核编译时没有启用 CONFIG_IPV6_SIT常见于某些精简内核。这种情况就别折腾了要么换内核要么考虑用用户态隧道工具。3.2 完整命令序列与逐条解读下面是本端 A 机上的完整配置命令全程只用 ifconfig最后用 ip 命令补一条静态路由这里的ip -6 route add只操作路由表不创建隧道所以不冲突# 1. 加载 sit 内核模块 modprobe sit # 2. 把模板设备 sit0 拉起来 ifconfig sit0 up # 3. 创建真正使用的隧道接口 sit1 # 有些系统会提示 Unknown device这一步就是为了解决这个问题 ifconfig sit1 create # 4. 指定隧道对端的 IPv4 地址 ifconfig sit1 tunnel 203.0.113.2 # 5. 给 sit1 配置本端 IPv6 地址 ifconfig sit1 inet6 add 2001:db8:1::2/64 # 6. 调整 MTU避免大包被中间链路丢弃 ifconfig sit1 mtu 1480 # 7. 启动隧道接口 ifconfig sit1 up # 8. 添加去往对端后侧网段的 IPv6 路由 ip -6 route add 2001:db8:2::/64 via 2001:db8:1::1 dev sit1每一条命令都需要理解为什么这样执行。第 2 步拉 sit0 是为了让内核把 sit 隧道相关的链路层状态激活如果不做这步后面的 sit1 可能处于一种奇怪的半初始化状态。第 4 步是关键中的关键tunnel 参数指定的是对端服务器的真实 IPv4 地址数据封装后外层 IPv4 头的目的地址就是这个地址。如果在系统里发现ifconfig sit1 create有报错大概率是 net-tools 版本比较老。可以用ifconfig sit1 tunnel 203.0.113.2直接触发内核自动创建 sit1不少场景下等价只是少了显式创建的清晰性。这里没有强制加local参数因为 ifconfig 不支持内核会自动选择到对端路由的源 IPv4 地址一般没问题但如果你有多块网卡、多个 IPv4 地址就需要警惕会不会选错源地址。作为对照同样场景用 iproute2 的等价命令是ip tunnel add sit1 mode sit remote 203.0.113.2 local 203.0.113.1 ttl 255 ip -6 addr add 2001:db8:1::2/64 dev sit1 ip link set sit1 mtu 1480 ip link set sit1 up ip -6 route add 2001:db8:2::/64 via 2001:db8:1::1 dev sit1对比很直观ip 命令能同时指定 local、remote、ttl管理粒度强很多。如果你手头系统有 iproute2强烈建议优先用 ip 命令建隧道ifconfig 的路子更适合紧急救火。3.3 隧道通没通怎么验证才靠谱接口配置完第一件事不是急着配业务路由而是先验证隧道链路本身。先 ping 对端的隧道地址ping6 -c 4 2001:db8:1::1如果通说明隧道已经建立起来。这里有个细节ping6 出来的延迟通常和物理链路相当但也不排除有波动。如果第一个包就是Destination unreachable先回头看 sit1 的对端地址和 IPv6 地址配置有没有写反不要急着怀疑防火墙。接着验证远端网段可达性ping6 -c 4 2001:db8:2::1这条命令如果通说明不仅隧道正常到对端后侧网段的路由也生效了。我还要建议你在抓包层面确认一次封装是否正确。在 A 机的物理网卡上抓包过滤外层协议号 41tcpdump -ni eth0 proto 41正常情况下你能看到从 203.0.113.1 发往 203.0.113.2 的 IPv4 包展开后会有一个 IPv6 头在里面。这一步能排除很多“感觉通了但实际靠的是别的方式”的错觉尤其是多隧道并存或系统里本身有 IPv6 默认路由时防止你 ping 通的流量其实走了其他路径。4. 上线首日最容易踩的坑从 MTU 到转发开关4.1 MTU 是罪魁祸首小包通、大包不通的根源sit 隧道最常见的诡异现象是ping 小包完全正常但一跑大数据传输就频繁超时或者 SSH 能连上但一执行大文件下载就卡死。问题几乎都出在 MTU 上。物理以太网链路的 MTU 通常是 1500sit 隧道把 IPv6 报文放进 IPv4 包里外层额外增加了 20 字节的 IPv4 头所以 sit 接口的 MTU 理论值应该是 1500 - 20 1480。如果中间还有 PPPoE、VLAN、MPLS 等额外开销还要进一步扣减 8 字节或更多。我在配置命令里已经显式设置了ifconfig sit1 mtu 1480这一点很多人会忽略。如果没有设置部分内核会使用一个不太合理的默认值导致“IPv6 报文 外层 IPv4 头”加起来的物理包超过链路上游的 MTU被中间设备静默丢弃。更隐蔽的是路径 MTU 发现失效问题。IPv6 协议栈依赖 ICMPv6 Packet Too Big 报文来发现链路 MTU但 ICMPv6 在防火墙里经常被拦。如果 ping -s 小包时正常、加上大 payload 后不通优先检查防火墙是不是把 ICMPv6 的 type 2 报文给丢了。临时验证时可以用ping6 -c 4 -s 1400 2001:db8:1::1逐步下调 -s 参数比如 1400、1300看哪个值开始通。找到最大值的边界再反过来调整 sit1 的 MTU。这是最直接的定位方法。4.2 私网 IPv4 与 NAT 环境为什么这条隧道怎么都起不来粉丝群里经常有人问“我在家用电脑按教程建 sit 隧道为什么就是不通”九成情况下因为家用网络是典型的私网 IP NAT 出口。sit、GRE、IPIP 这类静态隧道协议外层协议号不是 TCP 也不是 UDP而是 41IPv6-in-IPv4。家用路由器做 NAT 时只认识 TCP/UDP遇到协议号 41 的包基本不会正确处理大多数情况下直接丢弃少数路由器做了 ALG 支持也只是“能用但极其不稳定”。判断方法很简单。在隧道两端的物理网卡上分别抓包如果发现 A 机发出的外层 IPv4 包到了 B 机抓包里看不到就需要怀疑中间 NAT 设备。要么在路由器上配置端口转发并开放协议 41要么放弃这种静态隧道改用基于 UDP 的隧道工具。这个不是技巧问题是网络架构限制。4.3 转发开关、rp_filter 和防火墙的排查顺序隧道通了但两端主机之间 ping 通、后侧网段不通时先别急着改路由按照下面的链路顺序逐步检查第一IPv6 转发。Linux 默认是不转发 IPv6 报文的如果你的 A 机不只是自己访问 IPv6 网段还承担给内网其他机器转发流量的任务必须打开转发sysctl -w net.ipv6.conf.all.forwarding1 sysctl -w net.ipv6.conf.sit1.forwarding1第二rp_filter 反向路径过滤。这个坑我遇到过好几次。sit1 接口收到的 IPv6 包源地址可能来自内网网段如果系统开启了严格 rp_filter 模式报文会被当作伪造源地址直接丢弃。注意是 IPv4 的 rp_filter 还是 IPv6 的IPv6 栈也有类似过滤机制但更隐蔽。检查sysctl net.ipv4.conf.all.rp_filter sysctl net.ipv4.conf.sit1.rp_filter sysctl net.ipv6.conf.all.disable_ipv6如果发现 rp_filter 是 1严格模式建议先临时调成 0 测试隧道确认是这个原因后再按实际网络范围精细配置过滤规则不要长期全局关闭。第三防火墙放行。隧道协议本身需要放行 IPv4 协议号 41iptables -I INPUT -p 41 -j ACCEPT如果还需要转发到内网其他机器IPv6 转发链也要放行ip6tables -I FORWARD -i sit1 -j ACCEPT最后还有一类非常隐蔽的问题对端 B 机的 sit1 接口没配上 IPv6 地址或者远端路由写了对端网段但 B 机自己的 eth0 没开 IPv6。这类问题用ip addr或者ifconfig看一眼就能定位。5. 救急可以长期跑还得换更稳的方案5.1 手动命令的短板重启丢失、配置零散、难排障ifconfig 手建隧道最大的毛病是“一次性”。重启之后 sit1 设备消失路由消失一切回归原样。如果你靠一两条命令把隧道跑起来就不管下一次开机后业务直接断掉而且排障的时候很难想起来“哦隧道没配”。另外ifconfig 建隧道的信息不在系统网络配置里systemctl 不会自动恢复network 服务也不会去加载。如果你所在的团队有多人维护机器这种临时命令式配置对后继者极不友好。我之前接手一台机器时发现 sit1 配得很好但网上查不到任何配置记录最后翻了一个不起眼的脚本才找到源头。5.2 把 ifconfig 隧道固化成启动脚本如果实在没法换网络管理方式至少要做一个启动脚本把隧道配置固定下来。我自己常用的方式是把命令写进/usr/local/sbin/sit-up.sh然后注册成 systemd oneshot 服务。脚本内容#!/bin/sh modprobe sit ifconfig sit0 up # 如果 sit1 已存在先清理旧配置 ifconfig sit1 down 2/dev/null ifconfig sit1 del 2/dev/null ifconfig sit1 create ifconfig sit1 tunnel 203.0.113.2 ifconfig sit1 inet6 add 2001:db8:1::2/64 ifconfig sit1 mtu 1480 ifconfig sit1 up ip -6 route add 2001:db8:2::/64 via 2001:db8:1::1 dev sit1 2/dev/null把脚本加上执行权限再写一个 systemd unit[Unit] DescriptionSIT tunnel bring-up Afternetwork-online.target [Service] Typeoneshot ExecStart/usr/local/sbin/sit-up.sh RemainAfterExityes [Install] WantedBymulti-user.target启用并检查状态chmod x /usr/local/sbin/sit-up.sh systemctl daemon-reload systemctl enable sit-up.service systemctl start sit-up.service systemctl status sit-up.service这样隧道配置就从一个“临时命令”变成机器上的一个可管理单元重启后会自动恢复问题定位也清晰得多。如果机器没有 systemd只能放在 rc.local 里凑合但可维护性会差很多。5.3 新环境别再留恋 ifconfig几个更稳的替代方向如果你的系统支持 iproute2其实完全没必要在隧道创建这层用 ifconfig。ip tunnel add mode sit remote ... local ... ttl 255一条命令就把最重要的参数都定死了之后再用ip -6 addr add配地址思路清楚得多。再往上走现代发行版普遍支持 systemd-networkd 或 NetworkManager 管理隧道。以 systemd-networkd 为例可以写一个.netdev文件配置 sit 隧道由系统网络服务统一管理不需要额外脚本也能开机自动恢复。NetworkManager 同样支持在连接配置里定义隧道。这些方案的可视化程度、报错信息、持久化能力都远优于 ifconfig 手动操作。我的建议是ifconfig 隧道这套知识当作应急技能储备就好。遇到手边只有老系统的场景能快速拉通但新建环境、新建项目优先用 iproute2 和网络管理服务它们才是长期运维的正确姿势。5.4 安全提醒别把隧道裸奔在公网上最后提醒一个安全问题。sit 隧道的特性决定了如果你有一台具有公网 IPv4 地址的主机开了 sit0任何知道隧道参数的外部主机都可能尝试向你的 IPv6 侧发起连接。公网上扫描协议号 41 的自动化程序并不少。建议在防火墙层严格限制远端只放行来自已知隧道对端 IPv4 地址的协议号 41 流量其他地址一律丢弃。把隧道当成一条专用的点对点线路看待而不是一份开放的公共服务。配置 IP 放行时尽量精确到 /32避免大段掩码带来的风险。我实际在服务器上处理这类隧道时习惯同时看三样东西内核模块是否加载、隧道接口状态、路由表里是否有多余的默认 IPv6 路由。每次排障都从这三件事查起能省下不少时间。sit 隧道本身不复杂复杂的是那些藏在 MTU、NAT、防火墙和 sysctl 里的隐性坑。把这几个点记牢再碰到纯 ifconfig 环境下的 IPv6 接入需求你至少知道从哪下手了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑