【问题标题】:IP tunnel over Linux serial default shellLinux 串行默认 shell 上的 IP 隧道
【发布时间】:2015-01-08 10:15:29
【问题描述】:

这是this问题的更受限制的版本:

我有一个嵌入式 ARM 设备,它运行带有 Linux 3.10.0 内核的自定义映像。

唯一的物理接口(没有、USB、没有以太网)是连接到串行接口之一的默认 Linux shell。

我的问题是:是否有任何内置或外部工具可以通过此连接打开 IP 隧道?

我看到了一些一般性问题:

  • 该设备已被 Linux 使用,因此必须使用 stdin/out 进行通信,而不是直接访问该设备。
  • 启动隧道应用程序后,应用程序必须等待隧道客户端连接,因为我需要关闭计算机上的串行连接,然后再启动隧道客户端。
  • 应该有办法关闭连接并回到正常的shell

实际要求是,我可以从通过串行电缆连接到嵌入式设备的计算机访问在嵌入式设备上运行的 REST 接口。

这已经适用于具有物理以太网或 USB 以太网的设备,但此设备不提供。

[更新] 如前所述,socat 目前在我们的嵌入式设备上不可用,因此作为第一次尝试,我使用了以下内容:

  • 具有物理串行接口的 Linux (Ubuntu) 笔记本电脑
  • 一台装有物理串行接口并安装了 cygwin+socat 的 Windows 笔记本电脑
  • 两者均通过 Null 调制解调器电缆连接

注意:我在一侧使用的是 Windows 笔记本电脑,因为我们将在 Linux 上运行 socat 客户端(不幸的是)。

  1. 直接 STDIO 连接

服务器

socat stdio file:/dev/ttyS0,b115200

客户

socat file:/dev/ttyS4,b115200 stdio

在 cygwin 中,ttyS0COM1ttyS4 在这种情况下是 COM5

使用这些,socat 就像一个小聊天程序一样工作。为什么我在一侧输入是在另一侧输出,反之亦然。

  1. TCP 连接

下一步是使用 TCP 连接。

服务器

socat /dev/ttyS0,b115200,crtscts=1,raw,echo=0 tcp-connect:localhost:80

客户

socat -T2 file:/dev/ttyS4,b115200,crtscts=1,raw,echo=0 tcp-l:7777,reuseaddr

我指定了波特率 (115200),使用了原始传输,没有使用硬件流控制回显(否则 HTTP 请求将被发送回请求者)。脓我不得不使用超时-T2,它会在 2 秒后终止连接。否则,curl 也不会终止并等待更多数据。

当我在windows电脑上使用curl时,它通过串口成功传输请求,并返回Linux电脑上HTTP服务器的完整HTTP响应:

curl localhost:7777/index.html

但是,它只能工作一次。请求完成后,socatclient 和 server 都终止。

此外,当我使用浏览器 (Chorme) 时,它使用最有可能发送二进制字符的 g-zip 编码。其中一个字符将是EOF 字符,它在完成请求/响应之前再次终止socat

然后我尝试将fork添加到服务器:

socat /dev/ttyS0,b115200,crtscts=1,raw,echo=0 tcp-connect:localhost:80,fork

这使服务器保持活动状态,但curl 返回400 Bad Request。因此,似乎socat 服务器对每一行或每一块都发起了一个请求,因为它不理解 HTTP。

  1. IP 连接

然后我想到了下一层并使用 TUN 连接。但是,这在 socat 的 Windows 版本上没有实现。

  1. HTTP 连接

如果我错了,请纠正我,但据我了解,socat 没有提供真正理解 HTTP 并且能够通过串行连接正确序列化它的连接类型。

所以,我找不到任何稳定的方法来启动客户端和服务器并通过串行连接运行多个 HTTP 请求。

【问题讨论】:

    标签: linux serial-port ip tunnel


    【解决方案1】:

    在普通的 linux 上,你可以使用socat

    此程序允许您连接多种流类型(文件、套接字、tcp、udp...)。在您的情况下,它将是 tcp 文件或更准确地说是端口 xx 到 /dev/ttyUSB1 的 tcp 套接字。您应该在两侧启动 socat 以建立隧道。

    编辑 1:
    对不起,我也对 socat 感到失望。我找不到让我的 TCP 侦听器对多个连续连接保持活动状态但一次只处理一个连接的解决方案。

    我的解决方案是一个使用 4 个线程的简单 C# 程序: 1. 等待标准输入上的输入,例如退出命令 2. TCP监听器 3. 用于活动连接的 TCP 工作线程 4.如果TCP打开,则为COM打开另一个线程

    线程 3 从 TCP 读取并写入 COM,线程 4 从 COM 读取并写入 TCP。如果线程收到 TCP 关闭事件,它会停止关闭 COMx 的线程 4,并自行退出。现在线程 2 可以接受一个新的连接。如果线程 1 在 stdin 上读取 exit,它会向所有线程传递一条消息以停止和关闭。

    也许您可以在没有 socat 的嵌入式系统上使用 pthread 用 C 语言实现这样一个简短的程序。

    EOF 问题: 我试图用谷歌搜索一个程序,它可以转义特殊字符或将数据流从 ASCII 重新编码为 ANSI 或 base64 或其他...... p>

    Server <=> reencode <=> socat <--serial--> socat <=> reencode <=> client
    

    【讨论】:

    • 如前所述,我不能直接使用设备,因为没有可用的物理 USB 并且内核使用唯一的物理串行设备。但是,从手册页的内容来看,我认为在我的情况下,我需要在嵌入式端使用 STDIN / STDOUT,在另一端使用串行设备。 socat 是否在等待客户端连接以及如何关闭 socat 连接?
    • 是的,它正在等待。您还可以定义一个作为 EOF 或 TCP.close() 处理的字符。我正在以相反的方式使用 socat:通过 TCP 进行串行隧道传输。
    • 很遗憾,socat 在我们的目标系统上不可用,并且它不包含在我们的 BSP/构建系统中。这意味着,如果不添加自定义包并重建 Linux 映像,我将无法对其进行测试。但是,从手册页的内容来看,它完全符合我的需要,所以我接受了这个答案。一旦我测试了它,我会发布和更新。
    • 如果您能查看我更新的帖子,我将不胜感激。您有什么办法可以解决上述任何问题吗?
    • 感谢您的更新。是的,虽然 socat 非常强大且用途广泛,但似乎有一些特殊情况不起作用。在评估socat之前,我其实是在考虑自己写一个这样的工具。但我对重新发明轮子持怀疑态度。我认为使用串行线路需要一些基本的传输协议来转义控制字符,使用一些错误纠正/检测并允许更高级别的流控制来表示连接已关闭,例如
    【解决方案2】:

    我们现在已经使用pppd 解决了一半的问题。事实证明,即使是 Windows 也支持ppp。与socat 相比,pppd 实际上使用了一种包含错误检测的协议,它会在 Linux 和 Windows 系统上自动创建网络设备。

    唯一的问题是,pppd 需要访问串行设备。没有像ppp 工具提供的直接模式。

    我们现在正在按需禁用 shell,重新启动到 IP-over-serial 模式。完成后,我们重新启动系统,系统会使用串行线自动切换回getty

    这不是最漂亮的解决方案,但现在,它似乎有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 2021-05-13
      • 2013-07-28
      • 1970-01-01
      • 2012-06-13
      相关资源
      最近更新 更多