提前准备:

TAP (Network TAP):工作在数据链路层(第2层)。
TUN (Network TUNnel):工作在网络层(第3层)。传输加密的 IP 数据包,从而实现点到点的加密通信。虚拟的物理网络接口,用户态可以直接写数据。 数据包可以被操作系统协议栈进一步处理,就像该数据包是通过一个物理网络接口接收到的一样。

TAP设备:
数据链路层设备:模拟以太网设备,处理以太网帧。
无需网络协议栈处理:数据帧直接传递,不需要进入内核的网络协议栈。
内核传输这些帧:
这些数据帧可以直接被其它网络工具处理或发送到实际物理接口。
内核中的 bridge 设备将这些帧传递到物理接口,或者转发给其他虚拟设备。

TUN设备:
网络层设备:模拟网络层设备,处理IP包。
需要网络协议栈处理:IP包需要进入内核网络协议栈进行处理。
内核处理这些包:
内核接收这些IP包进行网络层处理(如路由决策、转发、NAT等)。
内核将处理后的IP包发送到实际物理接口,或交给其他网络程序进行处理。


如何使用tap呢?

// TAP 配置
let mut config = Configuration::default();
config
    .address((192, 168, 100, 1))
    .netmask((255, 255, 255, 0))
    .tap(true)  // 指定使用 TAP 模式
    .up();

// 创建并配置 TAP 设备
let mut dev = Device::new(&config).unwrap();
println!("TAP device created");

杂问杂答:A和B想要通过vpn进行通信。

  • 网络协议:可以有很多种方式,这里使用的udp.
  • udp里面传的是什么数据呢? wiregurad协议的数据, 一种vpn 协议。简单版本先不用考虑这个, 用一个加密的数据即可。
  • 整个过程有没有内核参与呢? 有!!!
  • 如果是tun的方式:用户态的!
  • 用户态加解密数据,写入到tun(虚拟的网卡)
  • 数据是怎么走到虚拟网卡的? 需要配置路由协议。
  • 分配给tun的IP是虚拟的,随便设计IP的地址吧,但是要有,有了才能走路由规则。

服务依赖:

rand = "0.8.5"
tun = "0.6.1"
x25519-dalek = { version = "2.0.1", features = ["static_secrets"] }
blake2 = "0.11.0-pre.4"

服务端:

use tokio::{
    net::UdpSocket,
    io::{self, AsyncReadExt, AsyncWriteExt},
};
use tun::platform::Device;
use tun::Configuration;
use x25519_dalek::StaticSecret;
use x25519_dalek::PublicKey;
use blake2::Blake2s;
use blake2::digest::{Update, VariableOutput};
use rand::rngs::OsRng;
use std::process::Command;

pub async fn run_server() {
    // TUN 配置
    let mut config = Configuration::default();
    config.address((10, 0, 0, 1)).netmask((255, 255, 255, 0)).up();

    let mut dev = Device::new(&config).unwrap();
    println!("Server TUN device created");

    // 配置路由
    configure_routing();

    // 加密密钥
    let server_privkey = StaticSecret::new(&mut OsRng);
    let server_pubkey = PublicKey::from(&server_privkey);
    let client_pubkey = PublicKey::from([0u8; 32]);  // 从配置文件或命令行读取或替换为实际的客户端公钥

    // UDP 套接字
    let socket = UdpSocket::bind("0.0.0.0:51820").await.unwrap();
    println!("Server listening on port 51820");

    let mut buf = [0u8; 1500];

    loop {
        let (size, addr) = socket.recv_from(&mut buf).await.unwrap();
        let decrypted = decrypt_data(&server_privkey, &client_pubkey, &buf[..size]);
        dev.write(&decrypted).unwrap();

        let size = dev.read(&mut buf).unwrap();
        let encrypted = encrypt_data(&server_privkey, &client_pubkey, &buf[..size]);
        socket.send_to(&encrypted, addr).await.unwrap();
    }
}

fn configure_routing() {
    // 删除现有的默认路由(如果有的话)
    let _ = Command::new("sudo").arg("ip").arg("route").arg("del").arg("default").output();

    // 添加新的默认路由通过 TUN 设备
    let _ = Command::new("sudo").arg("ip").arg("route").arg("add").arg("default").arg("dev").arg("utun0").output();

    // 确保 TUN 设备的网络范围内的流量也通过 TUN 设备
    let _ = Command::new("sudo").arg("ip").arg("route").arg("add").arg("10.0.0.0/24").arg("dev").arg("utun0").output();
}

fn encrypt_data(server_privkey: &StaticSecret, client_pubkey: &PublicKey, data: &[u8]) -> Vec<u8> {
    let shared_secret = server_privkey.diffie_hellman(client_pubkey);
    let key = blake2_key_derive(&shared_secret);
    // 使用对称加密(例如 ChaCha20)的逻辑进行加密
    data.to_vec()  // 暂时返回原数据
}

fn decrypt_data(server_privkey: &StaticSecret, client_pubkey: &PublicKey, data: &[u8]) -> Vec<u8> {
    let shared_secret = server_privkey.diffie_hellman(client_pubkey);
    let key = blake2_key_derive(&shared_secret);
    // 使用对称加密(例如 ChaCha20)的逻辑进行解密
    data.to_vec()  // 暂时返回原数据
}

fn blake2_key_derive(shared_secret: &x25519_dalek::SharedSecret) -> Vec<u8> {
    let mut hasher = Blake2s::new_keyed(shared_secret.as_bytes(), 32);
    hasher.update(b"WireGuard");
    let mut key = vec![0u8; 32];
    hasher.finalize_variable(|res| key.copy_from_slice(res));
    key
}

客户端:

use tokio::{
    net::UdpSocket,
    io::{self, AsyncReadExt, AsyncWriteExt},
};
use tun::platform::Device;
use tun::Configuration;
use x25519_dalek::StaticSecret;
use x25519_dalek::PublicKey;
use blake2::Blake2s;
use blake2::digest::{Update, VariableOutput};
use rand::rngs::OsRng;
use std::process::Command;

pub async fn run_client() {
    // TUN 配置
    let mut config = Configuration::default();
    config.address((10, 0, 0, 2)).netmask((255, 255, 255, 0)).up();

    let mut dev = Device::new(&config).unwrap();
    println!("Client TUN device created");

    // 配置路由
    configure_routing();

    // 加密密钥
    let client_privkey = StaticSecret::new(&mut OsRng);
    let client_pubkey = PublicKey::from(&client_privkey);
    let server_pubkey = PublicKey::from([0u8; 32]);  // 从配置文件或命令行读取或替换为实际的服务器公钥

    // UDP 套接字
    let socket = UdpSocket::bind("0.0.0.0:51820").await.unwrap();
    socket.connect("<公司公网IP>:51820").await.unwrap();
    println!("Connected to server");

    let mut buf = [0u8; 1500];

    loop {
        let size = dev.read(&mut buf).unwrap();
        let encrypted = encrypt_data(&client_privkey, &server_pubkey, &buf[..size]);
        socket.send(&encrypted).await.unwrap();

        let received_size = socket.recv(&mut buf).await.unwrap();
        let decrypted = decrypt_data(&client_privkey, &server_pubkey, &buf[..received_size]);
        dev.write(&decrypted).unwrap();
    }
}

fn configure_routing() {
    // 删除现有的默认路由(如果有的话)
    let _ = Command::new("sudo").arg("ip").arg("route").arg("del").arg("default").output();

    // 添加新的默认路由通过 TUN 设备
    let _ = Command::new("sudo").arg("ip").arg("route").arg("add").arg("default").arg("dev").arg("utun0").output();

    // 确保 TUN 设备的网络范围内的流量也通过 TUN 设备
    let _ = Command::new("sudo").arg("ip").arg("route").arg("add").arg("10.0.0.0/24").arg("dev").arg("utun0").output();
}

fn encrypt_data(client_privkey: &StaticSecret, server_pubkey: &PublicKey, data: &[u8]) -> Vec<u8> {
    let shared_secret = client_privkey.diffie_hellman(server_pubkey);
    let key = blake2_key_derive(&shared_secret);

    // 使用对称加密(例如 ChaCha20)的逻辑进行加密
    data.to_vec()  // 暂时返回原数据
}

fn decrypt_data(client_privkey: &StaticSecret, server_pubkey: &PublicKey, data: &[u8]) -> Vec<u8> {
    let shared_secret = client_privkey.diffie_hellman(server_pubkey);
    let key = blake2_key_derive(&shared_secret);

    // 使用对称加密(例如 ChaCha20)的逻辑进行解密
    data.to_vec()  // 暂时返回原数据
}

fn blake2_key_derive(shared_secret: &x25519_dalek::SharedSecret) -> Vec<u8> {
    let mut hasher = Blake2s::new_keyed(shared_secret.as_bytes(), 32);
    hasher.update(b"WireGuard");
    let mut key = vec![0u8; 32];
    hasher.finalize_variable(|res| key.copy_from_slice(res));
    key
}

putao
5 声望0 粉丝

推动世界向前发展,改善民生。