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(())
}
代码说明
search_gateway
- 异步搜索本地网络中的UPnP网关设备get_external_ip
- 获取路由器的外部IP地址add_port
- 添加端口映射:- 协议类型(TCP/UDP)
- 外部端口
- 内部IP地址
- 内部端口
- 映射有效期
- 描述信息
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(())
}
示例说明
- 首先搜索并连接到本地网络中的UPnP网关
- 获取路由器的外部IP地址
- 检查指定端口(8080)是否已有映射
- 如果不存在则添加新的端口映射
- 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"] }
注意事项
- 路由器必须启用UPnP功能
- 某些网络环境可能限制UPnP操作
- 端口映射有租期限制,到期后需要重新添加
- 生产环境应添加适当的错误处理和日志记录
- 考虑添加重试机制处理网络波动
这个完整的示例展示了如何使用igd库从发现设备到管理端口映射的完整流程,包含了同步和异步两种实现方式。