Rust端口映射工具库portmapper的使用,portmapper实现高效网络端口转发与NAT穿透功能

Rust端口映射工具库portmapper的使用

portmapper是一个Rust库,用于在网络变化时维护本地端口映射,支持UPnP、PCP和NAT-PMP协议。由n0团队开发,并用于iroh项目。

功能特点

  • 支持多种端口映射协议:UPnP、PCP、NAT-PMP
  • 自动维护端口映射
  • 高效网络端口转发
  • NAT穿透功能

安装

在Cargo.toml中添加依赖:

portmapper = "0.8.0"

或者运行命令:

cargo add portmapper

示例代码

首先展示内容中提供的示例:

// 示例代码将展示portmapper的基本用法

下面是完整的示例demo:

use portmapper::{PortMapper, MappingOptions, Protocol};
use std::time::Duration;

async fn create_port_mapping() -> Result<(), Box<dyn std::error::Error>> {
    // 创建PortMapper实例
    let pm = PortMapper::new();
    
    // 设置映射选项
    let options = MappingOptions {
        local_port: 8080,       // 本地端口
        external_port: 8080,    // 外部端口(可选,设为0则自动分配)
        protocol: Protocol::Tcp, // 协议类型
        lease_duration: Some(Duration::from_secs(3600)), // 租期时间
        description: Some("My Rust Service".to_string()), // 描述信息
    };
    
    // 创建端口映射
    let mapping = pm.create_mapping(options).await?;
    
    println!("端口映射创建成功!");
    println!("外部地址: {}", mapping.external_address);
    println!("外部端口: {}", mapping.external_port);
    
    // 保持映射有效
    loop {
        tokio::time::sleep(Duration::from_secs(1800)).await;
        pm.refresh_mapping(&mapping).await?;
    }
    
    // 映射会自动在Drop时删除
    // 也可以手动删除: pm.delete_mapping(&mapping).await?;
}

#[tokio::main]
async fn main() {
    if let Err(e) = create_port_mapping().await {
        eprintln!("端口映射失败: {}", e);
    }
}

协议支持

该库支持以下协议:

  1. UPnP (Universal Plug and Play)
  2. PCP (Port Control Protocol)
  3. NAT-PMP (NAT Port Mapping Protocol)

许可证

该项目采用双重许可:

  • Apache License, Version 2.0
  • MIT license

可根据需要选择其中一种。

贡献

除非您明确声明,否则您提交的任何贡献都将按照上述双重许可进行授权,无需任何附加条款或条件。


1 回复

Rust端口映射工具库portmapper使用指南

介绍

portmapper是一个Rust实现的网络端口映射工具库,主要用于实现高效的网络端口转发和NAT穿透功能。它可以帮助开发者轻松实现内网穿透、端口映射等网络功能,特别适合P2P应用、内网服务暴露等场景。

主要特性

  • 支持TCP/UDP端口转发
  • 内置NAT穿透能力
  • 高性能异步IO实现
  • 跨平台支持
  • 简洁易用的API接口

使用方法

添加依赖

[dependencies]
portmapper = "0.3"
tokio = { version = "1.0", features = ["full"] }

基本端口转发示例

use portmapper::PortMapper;
use tokio::io;

#[tokio::main]
async fn main() -> io::Result<()> {
    // 创建端口映射器实例
    let mapper = PortMapper::new();
    
    // 将本地的8080端口转发到远程的80端口
    mapper.forward("127.0.0.1:8080", "remote.server.com:80").await?;
    
    println!("端口转发已启动: 127.0.0.1:8080 -> remote.server.com:80");
    
    // 保持程序运行
    tokio::signal::ctrl_c().await?;
    Ok(())
}

NAT穿透示例

use portmapper::PortMapper;
use tokio::io;

#[tokio::main]
async fn main() -> io::Result<()> {
    let mapper = PortMapper::new();
    
    // 尝试穿透NAT并建立P2P连接
    let peer_addr = "peer.public.ip:12345";
    let local_service = "127.0.0.1:8080";
    
    mapper.punch_nat(peer_addr, local_service).await?;
    
    println!("NAT穿透成功,本地服务 {} 可通过P2P连接访问", local_service);
    
    tokio::signal::ctrl_c().await?;
    Ok(())
}

高级配置示例

use portmapper::{PortMapper, Config};
use std::time::Duration;

#[tokio::main]
async fn main() -> io::Result<()> {
    // 自定义配置
    let config = Config {
        heartbeat_interval: Duration::from_secs(30),
        timeout: Duration::from_secs(10),
        max_retries: 3,
        ..Default::default()
    };
    
    let mapper = PortMapper::with_config(config);
    
    // 设置多个转发规则
    mapper.forward("127.0.0.1:8080", "service1.example.com:80").await?;
    mapper.forward("127.0.0.1:8081", "service2.example.com:443").await?;
    
    println!("多端口转发已配置");
    
    tokio::signal::ctrl_c().await?;
    Ok(())
}

完整示例demo

下面是一个结合端口转发和NAT穿透功能的完整示例:

use portmapper::{PortMapper, Config};
use std::time::Duration;
use tokio::io;

#[tokio::main]
async fn main() -> io::Result<()> {
    // 1. 初始化带自定义配置的端口映射器
    let config = Config {
        heartbeat_interval: Duration::from_secs(20),
        timeout: Duration::from_secs(15),
        max_retries: 5,
        ..Default::default()
    };
    
    let mapper = PortMapper::with_config(config);
    
    // 2. 设置端口转发规则
    // 将本地8080端口转发到远程Web服务
    mapper.forward("127.0.0.1:8080", "web.example.com:80").await?;
    
    // 将本地8081端口转发到远程数据库
    mapper.forward("127.0.0.1:8081", "db.example.com:3306").await?;
    
    // 3. 尝试NAT穿透建立P2P连接
    let peer_ip = "123.45.67.89:54321"; // 对端公网IP和端口
    let local_service = "127.0.0.1:8082"; // 本地需要暴露的服务
    
    match mapper.punch_nat(peer_ip, local_service).await {
        Ok(_) => println!("NAT穿透成功,P2P连接已建立"),
        Err(e) => eprintln!("NAT穿透失败: {}", e),
    }
    
    println!("所有服务已启动:");
    println!("- 本地8080端口 -> web.example.com:80");
    println!("- 本地8081端口 -> db.example.com:3306");
    println!("- P2P服务在8082端口");
    
    // 4. 保持程序运行直到收到Ctrl+C信号
    tokio::signal::ctrl_c().await?;
    println!("正在关闭服务...");
    Ok(())
}

常见使用场景

  1. 内网服务暴露:将内网开发的服务临时暴露到公网
  2. P2P应用:实现点对点直接通信,绕过NAT限制
  3. 服务迁移:在不中断服务的情况下迁移服务到新端口
  4. 负载测试:将测试流量转发到不同后端服务

注意事项

  • 使用NAT穿透功能需要至少一端在非对称NAT后
  • 端口转发会带来一定的性能开销
  • 生产环境使用时建议添加适当的错误处理和日志记录
  • 某些网络环境可能限制端口转发功能

portmapper库提供了强大的网络功能,但使用时应当遵守当地法律法规和网络使用政策。

回到顶部