Skip to content

A lightweight Layer 2 VPN implementation based on Linux TAP and UDP encapsulation. (基于 TAP 和 UDP 的二层云端虚拟交换机)

License

Notifications You must be signed in to change notification settings

Cyans1314/Simple-L2-VPN

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Simple L2-VPN: 基于 TAP 的二层云端虚拟交换机

Language Language License Platform Status

"让位于世界两端的计算机,以为自己连在同一根网线上。"

这是一个基于 Linux TAP 虚拟网络设备UDP 封装技术 的轻量级二层 VPN 实现。本项目旨在解决复杂网络环境下的内网穿透与 IP 冲突问题,通过在云端实现一个 Software Defined Switch (软件定义交换机),构建一个跨越物理边界的虚拟二层局域网。


🎓 1. 项目灵感 (Inspiration)

灵感来源:一次计算机网络实验

本项目的灵感来源于大学计算机网络课程中的经典实验——《VLAN 划分与三层交换》。 在实验中,我们通过配置三层交换机的路由表和 VLAN 网关,让不同网段的 PC 实现了互联。这种物理层面的网络构建既直观又迷人。

灵感来源 (图 1: 传统实验中的物理拓扑与 VLAN 隔离激发了本项目的设计灵感)

现实世界的痛点

然而,当我试图将实验原理应用到真实互联网时,遇到了无法逾越的物理障碍:

  • IP 地址冲突:绝大多数家庭和企业局域网都默认使用了 192.168.1.x 网段。如果你想把两个地点的局域网连起来,IP 冲突会导致路由表彻底瘫痪。
  • NAT 高墙:由于 IPv4 地址枯竭,几乎所有终端都躲在 NAT(网络地址转换)防火墙后面,外网无法主动发起连接。
  • 三层路由限制:公网路由器只负责转发公网 IP,它看不懂也不关心你内网的以太网帧。

为了打破这些物理限制,我决定下沉到 OSI 模型的第二层(数据链路层),用软件模拟一条“云端网线”。


✨ 2. 核心特性 (Features)

本项目通过 Overlay Network(覆盖网络)技术,实现了以下特性:

  • 二层透明传输:不仅能转发 IP 数据包,还能转发 ARP、DHCP 等非 IP 协议的以太网帧。
  • 零配置 IP 漫游:即使 Client A 和 Client B 在物理上位于不同城市,且都拥有完全相同的本地私有 IP,它们依然可以通过本系统通信,互不干扰。
  • 穿透 NAT:利用 UDP 协议的无连接特性,轻松穿透常见的 NAT 设备,无需配置复杂的端口映射。
  • 自学习交换机:云端 Python 服务端实现了标准交换机的 MAC 地址学习算法,维护 CAM 表,智能决策是单播转发还是广播泛洪。

🏗️ 3. 系统架构与原理 (Architecture)

技术栈

  • 客户端 (Edge): C Language + Linux Kernel TAP Driver + Raw Socket
  • 服务端 (Cloud): Python 3 + SocketServer

数据流转全过程

当 Client A 想要给 Client B 发送数据时,流程如下:

  1. 打包:Client A 的内核将数据生成以太网帧,写入虚拟网卡 qwq。C 程序读取该帧,给它套上一个 UDP 头部。
  2. 运输:UDP 包通过物理网卡发出,经过复杂的互联网路由,到达云端 Server。
  3. 分拣:Python 服务端拆开 UDP 包,查看内部以太网帧的 Destination MAC
    • 如果是新地址:记录源 MAC 和来源 IP。
    • 如果是已知地址:查找 MAC 表,找到 Client B 的隧道信息。
  4. 投递:Server 将包转发给 Client B。Client B 的 C 程序收到后,剥去 UDP 头部,将原始帧写入自己的 qwq
  5. 收货:Client B 的内核以为刚才那个数据包是从网线上过来的,正常处理。

💻 4. 核心代码解析 (Analysis)

(1) tap.c - 虚拟设备构建

封装了 Linux TAP 设备的底层交互逻辑。

  • 机制:打开 /dev/net/tun 并通过 ioctl(TUNSETIFF) 注册设备。
  • 关键标志
    • IFF_TAP:指定设备工作在二层(处理 Ethernet Frame)。
    • IFF_NO_PI:禁用内核附加的 Packet Info 头部,确保读写的是纯净以太网帧。
  • 作用:建立用户态程序与内核网络栈的“秘密通道”。

(2) client.c - 多线程数据泵

采用 pthread 实现全双工通信,核心结构体 struct Vport 统一管理 TAP 句柄与 UDP Socket。

  • 上行线程 (upstream_thread)
    • 阻塞读取 TAP 设备数据(捕获内核发出的帧)。
    • 通过 sendto 将原始帧作为 UDP 载荷发往 Server。
  • 下行线程 (downstream_thread)
    • 监听 UDP 端口,接收云端数据。
    • 通过 write 将帧注入 TAP 设备,模拟物理网卡收包,“欺骗”内核进行协议栈处理。

(3) vswitch.py - 云端交换逻辑

Python 实现的轻量级 UDP 交换机,手动解析前 14 字节以太网头部。

  • MAC学习:动态维护 MAC -> (Client_IP, Port) 映射表,实时更新主机位置。
  • 转发策略
    • 已知单播:查表命中,精确转发。
    • 广播 (ff:ff:ff:ff:ff:ff):向表中除源地址外的所有活跃客户端泛洪。
    • 未知单播:为防止网络风暴,对于表中不存在的目标 MAC,策略为直接丢弃 (Drop)

🚀 5. 快速开始 (Quick Start)

事实上我们可以使用 GNS3 搭建一个拓扑图进行抓包来验证程序,拓扑图如下:

alt text (图 2: 用拓扑图模拟网络环境)

  1. 前置准备:Server-VSwitch 和 PC 机均为 Ubuntu Server,需要将代码拷入。
  2. Server-VSwitch:在服务器端运行脚本监听端口:
    python3 vswitch.py 9999
  3. Ubuntu-PC:编译 C 客户端,并运行配置脚本:
    # 编译
    gcc -o client tap.c client.c common.c -I. -lpthread
    # 运行 (需确保 run.sh 已配置正确 IP)
    sudo sh run.sh
  4. 验证:Ping 对方虚拟 IP,并使用 tcpdump 抓包验证二层连通性。

🎮 6. 有趣的玩法 (Fun)

如果你和你的小伙伴拥有 Linux 环境以及一台云服务器,可以将这个底层项目应用起来,做一些有意思的实验: 我在项目中附带了一个 chat.py,这是一个基于 Python tkinter 库编写的简陋对话窗口。

  • 配置:修改代码中的 ROLE (角色) 以及服务器 IP。
  • 运行:在两台通过 VPN 连通的主机上直接运行 python3 chat.py
  • 效果:数据包将通过我们的 UDP 隧道透明传输,你可以体验一下在这个自己亲手搭建的虚拟局域网中聊天的感觉!

About

A lightweight Layer 2 VPN implementation based on Linux TAP and UDP encapsulation. (基于 TAP 和 UDP 的二层云端虚拟交换机)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published