#port #udp-socket #mapping #nat #protocols #pcp #nat-pmp

crabnat

一个提供NAT端口映射协议(NAT-PMP)和端口控制协议(PCP)客户端纯Rust实现的库

13个版本 (5个重大变更)

0.6.4 2024年5月19日
0.6.3 2024年3月25日
0.6.1 2024年2月23日
0.5.3 2024年2月18日
0.1.0 2024年2月5日

#406网络编程

Download history 170/week @ 2024-05-13 37/week @ 2024-05-20 1/week @ 2024-06-10 31/week @ 2024-07-01

每月下载量 1,155

MIT 许可证

75KB
1.5K SLoC

🦀 NAT

一个提供NAT端口映射协议(NAT-PMP,RFC 6886)和端口控制协议(PCP,RFC 6887)客户端纯Rust实现的库。

此库旨在感觉像高级、惯用的Rust,同时仍然保持对性能的强烈关注。它是异步的,并使用tokio运行时以避免阻塞操作,并简洁地处理UDP套接字的超时。

使用方法

如果没有指定使用的端口映射协议或外部端口号等,使用方法如下

// Attempt a port mapping request through PCP first and fallback to NAT-PMP.
let mapping = match crab_nat::PortMapping::new(
    gateway, /* Address of the PCP server, often a gateway or firewall */
    local_address, /* Address of our client, as seen by the gateway. Only used by PCP */
    crab_nat::InternetProtocol::Tcp, /* Protocol to map */
    std::num::NonZeroU16::new(8080).unwrap(), /* Internal port, cannot be zero */
    crab_nat::PortMappingOptions::default(), /* Optional configuration values, including suggested external port and lifetimes */
)
.await
{
    Ok(m) => m,
    Err(e) => return eprintln!("Failed to map port: {e:?}"),
};

// ...

// Try to safely drop the mapping.
if let Err((e, m)) = mapping.try_drop().await {
    eprintln!("Failed to drop mapping {}:{}->{}: {e:?}", m.gateway(), m.external_port(), m.internal_port());
} else {
    println!("Successfully deleted the mapping...");
}

Crab NAT不确定网关地址或本地客户端地址。这是为了减少对此库使用方式的假设。为了提供一个易于使用的API来可靠地确定这些值,我建议使用netdev;请参阅基本使用示例client

包特性

  • tracing:启用使用tracing包记录UDP数据包重试尝试。目前仅在INFO详细程度下显示UDP重试尝试。

缺失实现细节

  • NAT-PMP
  • PCP
    • https://www.rfc-editor.org/rfc/rfc6887#section-11.1指出,错误上的生命周期值表示错误将持续多长时间。此信息未返回给调用者。
    • PCP支持比UDP和TCP更多的协议,这些协议尚未添加。如果需要,我愿意支持更多协议。
    • PCP定义了一些未实现的操作选项 Options。如果需要,我愿意支持一些选项。
    • PCP描述了一个 Announce 操作,我计划不实现它。

依赖项

~3–11MB
~115K SLoC