我想在我的周末小屋里部署一个 Raspberry Pi。Raspberry Pi 可以记录温度并将其发送到具有固定 IP 的远程服务器,保存数据并将其显示在一个简单的网站上。
然而,有时我想在 Raspberry Pi 上做些更改。例如系统更新或更改将数据发送到服务器的程序等。
使用建议的设置,我将无法从其 LAN 外部连接到 Raspberry Pi。
笔记:我不想改变网络,现有的路由器没有端口转发、dynDNS 或 VPN 功能。
我最近读了 UDP 打洞技术。基本思想是,客户端将 UDP 包发送到已知服务器地址(即启用了公共 IP 或 dynDNS)。想要连接到客户端 A 的客户端 B 向服务器询问客户端 A 的公共 IP 和端口号。
然后它可以直接通过其动态的公共 IP 和端口连接到客户端 A。由于客户端 A 首先通过现在使用的端口连接到服务器,因此 NAT 会将数据包转发给客户端 A。
我希望我或多或少正确地总结了这个想法......
这一切听起来不错,但问题是,这不能保证与 TCP 连接一起工作,因为路由器能够“理解” TCP 连接的握手,如果没有正确建立,它将不会转发数据包。
那么,我如何才能打开从客户端 B 到客户端 A 的 SSH 会话,而客户端 A 无需位于具有 dynDNS、固定公共 IP 或端口转发功能的路由器后面?使用具有公共、固定 IP 或域名的中央服务器可能会很困难。
答案1
pwnat
“...建立与NAT 后面的对等体。“
“..几乎全部NAT实现拒绝转发入站流量这并不对应于最近匹配的出站请求。“
“..这
pwnat
工具是一种仅限 GNU/Linux,独立实施自主 NAT 穿越。联系NAT 后面的服务器,它建立了一个渠道TCP 语义,使用UDP 数据包。它支持两者NAT 后面的客户端和服务器(如果其中一个 NAT 允许假[自定义] ICMP发送消息)。此实现以最终用户为目标。“
用法:./pwnat <-s | -c> <args> -c 客户端模式 <args>: [本地 ip] <本地端口> <代理主机> [代理端口 (def:2222)] <远程主机> <远程端口> -s 服务器模式 <args>: [本地 ip] [代理端口 (def:2222)] [[允许的主机]:[允许的端口] ...] -6 使用 IPv6 -v 显示调试输出(最多 2 个) -h 显示帮助并退出 例子: 服务器端允许任何人代理: ./pwnat -s 客户端想要连接到 google.com:80: ./pwnat -c 8000 <pwnat.server.com> google.com 80 然后,浏览http://localhost:8000 访问google!
“实现服务器到了解客户端的 IP 地址是为了服务器到定期向固定的、已知的 IP 地址发送消息。最简单的方法是使用 ICMP ECHO REQUEST 消息未分配的 IP 地址,例如 1.2.3.4。由于 1.2.3.4 未分配,因此 ICMP 请求没有默认路由的路由器将不会对其进行路由。“
“由于向 1.2.3.4 发送了消息,NAT 将启用回复路由,作为响应对此请求。连接然后客户端就会伪造这样的回复。具体来说,客户端将发送一个 ICMP 消息,表明
TTL_EXPIRED
。任何互联网路由器都可以合法地发送这样的消息,并且发送方地址预计与服务器的目标 IP 不匹配。““服务器监听(假的)ICMP回复和收到后,启动与发送方 IP 的连接ICMP 回复中指定。如果客户端使用全局可路由的 IP 地址,这完全没有问题,而且TCP 或 UDP 可用于建立双向连接如果客户倾听在预先约定的港口。“
“(在没有预先商定港口的情况下,大多数情况下,端口号可以作为有效载荷的一部分进行通信的 ICMP ECHO RESPONSE)。
答案2
以下是几个解决方案:
您可以设置您的 Raspberry Pi 以重新连接到 OpenVPN 服务器,并且您将可以随时访问它。
您可以查看 PageKite。检查https://pagekite.net/wiki/Howto/SshOverPageKite/
答案3
这是一个有点肮脏但简单的解决方案,但是使用 netcat 怎么样?在 Raspberry Pi 上,您可以创建一个循环执行以下命令的脚本:
nc <public_ip> <port1> | sh | nc <public_ip> <port2>
在本地主机上执行以下操作:
nc -l <port1>
和:
nc -l <port2>
您将能够在第一个实例中键入命令,并在第二个实例中看到响应。