Rust网络编程库igd的使用:实现UPnP协议,轻松管理家庭网络端口映射

Rust网络编程库igd的使用:实现UPnP协议,轻松管理家庭网络端口映射

Internet Gateway Device客户端

这是一个简单的库,可以与支持UPnP的网关设备(路由器)通信。欢迎贡献和反馈。

目前,您可以:

  • 搜索网关
  • 请求网关的外部地址
  • 添加/删除端口映射

请查看examples/文件夹中的示例演示。

测试需要非常谨慎,如果您在使用过程中遇到问题,请提交问题。

许可证: MIT

安装

在项目目录中运行以下Cargo命令:

cargo add igd

或者在Cargo.toml中添加以下行:

igd = "0.12.1"

完整示例代码

以下是一个使用igd库实现UPnP协议进行端口映射的完整示例:

use igd::{aio::search_gateway, AddPortError, PortMappingProtocol, SearchOptions};
use std::{net::Ipv4Addr, time::Duration};

#[tokio::main]
async fn main() -> Result<(), AddPortError> {
    // 搜索网关设备,设置10秒超时
    let gateway = search_gateway(SearchOptions {
        timeout: Some(Duration::from_secs(10)),
        ..Default::default()
    })
    .await?;

    // 获取外部IP地址
    let external_ip = gateway.get_external_ip().await?;
    println!("External IP地址: {}", external_ip);

    // 添加端口映射
    gateway
        .add_port(
            PortMappingProtocol::TCP,
            8080,                  // 外部端口
            Ipv4Addr::LOCALHOST,   // 内部IP地址
            8080,                  // 内部端口
            3600,                  // 映射有效期(秒)
            "Rust IGD示例",        // 描述
        )
        .await?;

    println!("成功添加端口映射: 8080 TCP -> 127.0.0.1:8080");

    // 删除端口映射
    gateway
        .remove_port(PortMappingProtocol::TCP, 8080)
        .await?;

    println!("成功删除端口映射");

    Ok(())
}

代码说明

  1. search_gateway - 异步搜索本地网络中的UPnP网关设备
  2. get_external_ip - 获取路由器的外部IP地址
  3. add_port - 添加端口映射:
    • 协议类型(TCP/UDP)
    • 外部端口
    • 内部IP地址
    • 内部端口
    • 映射有效期
    • 描述信息
  4. remove_port - 删除端口映射

注意: 此代码需要tokio运行时支持,请在Cargo.toml中添加tokio依赖。

完整示例demo

以下是一个更完整的示例,展示了如何检查端口映射是否存在并添加映射:

use igd::{aio::search_gateway, AddPortError, PortMappingProtocol, SearchOptions};
use std::{net::Ipv4Addr, time::Duration};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 搜索网关设备
    let gateway = search_gateway(SearchOptions {
        timeout: Some(Duration::from_secs(10)),
        ..Default::default()
    })
    .await?;

    // 获取外部IP
    let external_ip = gateway.get_external_ip().await?;
    println!("路由器外部IP: {}", external_ip);

    // 检查端口映射是否已存在
    let port = 8080;
    match gateway.get_generic_port_mapping_entry(0).await {
        Ok(entry) if entry.external_port == port => {
            println!("端口 {} 映射已存在: {} -> {}", 
                port, entry.external_port, entry.internal_client);
        }
        _ => {
            // 添加新的端口映射
            gateway
                .add_port(
                    PortMappingProtocol::TCP,
                    port,
                    Ipv4Addr::LOCALHOST,
                    port,
                    3600,
                    "Rust IGD示例",
                )
                .await?;
            println!("成功添加端口映射: {} TCP -> 127.0.0.1:{}", port, port);
        }
    }

    // 10秒后自动删除映射
    tokio::time::sleep(Duration::from_secs(10)).await;
    gateway.remove_port(PortMappingProtocol::TCP, port).await?;
    println!("已自动删除端口映射");

    Ok(())
}

示例说明

  1. 首先搜索并连接到本地网络中的UPnP网关
  2. 获取路由器的外部IP地址
  3. 检查指定端口(8080)是否已有映射
  4. 如果不存在则添加新的端口映射
  5. 10秒后自动删除该映射

这个示例展示了更完整的端口映射管理流程,包括检查现有映射和自动清理功能。


1 回复

Rust网络编程库igd的使用:实现UPnP协议,轻松管理家庭网络端口映射

介绍

igd是一个Rust实现的UPnP协议库,专门用于与支持UPnP(通用即插即用)协议的路由器交互。通过这个库,开发者可以轻松实现家庭网络中的端口映射管理,无需手动配置路由器。

该库主要功能包括:

  • 自动发现局域网中的UPnP设备
  • 添加/删除端口映射规则
  • 查询已有的端口映射
  • 获取外部IP地址
  • 支持IPv4和IPv6

完整示例代码

下面是一个完整的示例,展示了如何使用igd库进行端口映射管理:

use igd::{search_gateway, PortMappingProtocol};
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 发现网关设备(设置5秒超时)
    let options = igd::SearchOptions {
        timeout: Some(Duration::from_secs(5)),
        ..Default::default()
    };
    
    let gateway = search_gateway(options)?;
    println!("UPnP网关发现成功: {:?}", gateway);

    // 2. 获取外部IP地址
    let external_ip = gateway.get_external_ip()?;
    println!("外部IP地址: {}", external_ip);

    // 3. 添加TCP端口映射
    let external_port = 8080;
    let internal_ip = "192.168.1.100";
    let internal_port = 80;
    let lease_duration = 3600; // 1小时
    
    gateway.add_port(
        PortMappingProtocol::TCP,
        external_port,
        internal_ip,
        internal_port,
        lease_duration,
        "Rust UPnP示例"
    )?;
    println!("成功添加端口映射: {} -> {}:{}", external_port, internal_ip, internal_port);

    // 4. 查询现有端口映射
    println!("当前端口映射列表:");
    let mappings = gateway.get_port_mappings()?;
    for mapping in mappings {
        println!(" - {:?}", mapping);
    }

    // 5. 删除端口映射
    gateway.remove_port(PortMappingProtocol::TCP, external_port)?;
    println!("已删除端口映射: {}", external_port);

    Ok(())
}

异步完整示例代码

use igd::aio::search_gateway;
use igd::PortMappingProtocol;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 异步发现网关设备
    let options = igd::SearchOptions {
        timeout: Some(Duration::from_secs(5)),
        ..Default::default()
    };
    
    let gateway = search_gateway(options).await?;
    println!("UPnP网关发现成功(异步): {:?}", gateway);

    // 2. 异步获取外部IP
    let external_ip = gateway.get_external_ip().await?;
    println!("外部IP地址: {}", external_ip);

    // 3. 异步添加端口映射
    let external_port = 8080;
    let internal_ip = "192.168.1.100";
    let internal_port = 80;
    
    gateway.add_port(
        PortMappingProtocol::TCP,
        external_port,
        internal_ip,
        internal_port,
        3600,
        "异步Rust UPnP示例"
    ).await?;
    println!("异步添加端口映射成功");

    // 4. 异步查询映射
    println!("当前端口映射:");
    let mappings = gateway.get_port_mappings().await?;
    for mapping in mappings {
        println!(" - {:?}", mapping);
    }

    // 5. 异步删除映射
    gateway.remove_port(PortMappingProtocol::TCP, external_port).await?;
    println!("异步删除端口映射成功");

    Ok(())
}

Cargo.toml 配置

对于基本同步功能:

[dependencies]
igd = "0.17"

对于异步功能:

[dependencies]
igd = { version = "0.17", features = ["async"] }
tokio = { version = "1.0", features = ["full"] }

注意事项

  1. 路由器必须启用UPnP功能
  2. 某些网络环境可能限制UPnP操作
  3. 端口映射有租期限制,到期后需要重新添加
  4. 生产环境应添加适当的错误处理和日志记录
  5. 考虑添加重试机制处理网络波动

这个完整的示例展示了如何使用igd库从发现设备到管理端口映射的完整流程,包含了同步和异步两种实现方式。

回到顶部