IP-туннель через последовательную оболочку Linux по умолчанию

Это более ограниченная версия этого вопроса:

У меня есть встроенное устройство ARM с пользовательским образом с ядром Linux 3.10.0.

Единственный физический интерфейс (нет, USB, нет Ethernet) — это оболочка Linux по умолчанию, к которой подключен один из последовательных интерфейсов.

Мой вопрос: есть ли какой-либо встроенный или внешний инструмент, который открывает IP-туннель через это соединение?

Я вижу некоторые общие проблемы:

  • Устройство уже используется Linux, поэтому оно должно использовать stdin/out для связи вместо прямого доступа к устройству.
  • После запуска приложения туннелирования оно должно ждать подключения клиента туннеля, потому что мне нужно закрыть последовательное соединение на моем компьютере, а затем запустить клиент туннеля.
  • Должен быть способ закрыть соединение и вернуться к обычной оболочке.

Фактическое требование состоит в том, что я могу получить доступ к интерфейсу REST, работающему на встроенном устройстве, с компьютера, подключенного к встроенному устройству через последовательный кабель.

Это уже работает на устройствах с физическим Ethernet или Ethernet-over-USB, но это устройство не предлагает этого.

[ОБНОВЛЕНИЕ] Как уже объяснялось, в настоящее время socat недоступен на нашем встроенном устройстве, поэтому в качестве первой попытки я использовал следующее:

  • Ноутбук Linux (Ubuntu) с физическим последовательным интерфейсом
  • Ноутбук Windows с физическим последовательным интерфейсом и установленным cygwin+socat
  • Оба подключены через нуль-модемный кабель

Примечание. С одной стороны я использую ноутбук с Windows, потому что у нас будет клиент socat, работающий на Linux (к сожалению).

  1. Прямое подключение STDIO

Сервер

socat stdio file:/dev/ttyS0,b115200

Клиент

socat file:/dev/ttyS4,b115200 stdio

В cygwin ttyS0 это COM1, ttyS4 в данном случае это 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 также не завершает работу и ожидает дополнительных данных.

Когда я использую curl на компьютере с Windows, он успешно передает запрос через последовательное соединение и возвращает полный HTTP-ответ HTTP-сервера на компьютере с Linux:

curl localhost:7777/index.html

Однако это работает только один раз. После завершения запроса и socatclient, и сервер завершают работу.

Более того, когда я использую браузер (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-запросов через последовательное соединение.


person jaw    schedule 08.01.2015    source источник


Ответы (2)


В обычном Linux вы можете использовать socat.

Эта программа позволяет подключать несколько типов потоков (файл, сокет, tcp, udp, ...). В вашем случае это будет tcp для файла или, точнее, tcp-сокет на порту xx для /dev/ttyUSB1. Вы должны запустить сокат с обеих сторон, чтобы построить туннель.

Редактировать 1:
Извините, меня также разочаровал socat. Я не могу найти решение, которое поддерживало бы мой прослушиватель TCP активным для нескольких последовательных подключений, но одновременно обрабатывало бы только одно подключение.

Мое решение — простая программа на С#, использующая 4 потока: 1. дождаться ввода на стандартный ввод, например. команда выхода 2. прослушиватель TCP 3. рабочий поток TCP для активного соединения 4. если TCP открыт, он открывает другой поток для COM

Поток 3 читает из TCP и записывает в COM, а поток 4 читает из COM и записывает в TCP. Если поток получает событие закрытия TCP, он останавливает поток 4, который закрывает COMx, и сам завершает работу. Теперь поток 2 может принять новое соединение. Если поток 1 читает выход на стандартный ввод, он передает сообщение всем потокам, чтобы остановить и завершить работу.

Может быть, вы сможете реализовать такую ​​короткую программу на C с pthreads в своей встроенной системе, в которой нет socat.

Проблема с EOF: я пытался найти в Google программу, которая экранирует специальный символ или перекодирует поток данных из ASCII в ANSI или base64 или что-то еще... Если вы можете найти такую ​​программу или написать ее также на C, вы можете передать ее между

Server <=> reencode <=> socat <--serial--> socat <=> reencode <=> client
person Paebbels    schedule 09.01.2015
comment
Как объяснено, я не могу напрямую использовать устройство, поскольку физического USB-накопителя нет, а единственное физическое последовательное устройство используется ядром. Однако из того, что говорится на странице руководства, я думаю, что в моем случае мне нужно использовать STDIN / STDOUT на встроенной стороне и последовательное устройство на другой стороне. Ожидает ли socat, пока не подключится клиент, и как закрыть соединение socat? - person jaw; 09.01.2015
comment
Да ждет. Вы также можете определить символ, который обрабатывается как EOF или TCP.close(). Я использую socat наоборот: туннелирование последовательного порта через TCP. - person Paebbels; 09.01.2015
comment
К сожалению, socat недоступен в нашей целевой системе и не включен в нашу систему BSP/сборки. Это означает, что я не могу протестировать его без добавления пользовательского пакета и пересборки образа Linux. Однако, судя по тому, что написано на справочной странице, он делает именно то, что мне нужно, поэтому я принимаю этот ответ. Как только протестирую, отпишусь и обновлю. - person jaw; 12.01.2015
comment
Я был бы признателен, если бы вы могли взглянуть на мою обновленную публикацию. Видите ли вы какой-либо способ обойти любую из упомянутых проблем? - person jaw; 21.01.2015
comment
Спасибо за ваше обновление. Да, хотя сокат очень мощный и универсальный, кажется, что есть несколько особых случаев, которые не будут работать. Перед оценкой socat я действительно думал о написании такого инструмента самостоятельно. Но я скептически относился к изобретению велосипеда. Я думаю, что для использования последовательной линии требуется какой-то базовый транспортный протокол, который экранирует управляющие символы, использует некоторую коррекцию/обнаружение ошибок и позволяет управлять потоком на более высоком уровне, чтобы сигнализировать о том, что соединение закрыто, например. - person jaw; 22.01.2015
comment
Мой вариант использования — плата FPGA с UART @ 1 Мбит/с. Я хотел получить доступ к своей доске из дома, через университетский брандмауэр и через мою рабочую станцию. Поэтому я туннелирую UART через TCP. Одной из проблем является повторное использование соединения, потому что я хотел, чтобы socat оставался в живых, если я отключаюсь и снова подключаюсь на стороне TCP. И я хотел, чтобы socat ограничивал количество подключений до 1, чтобы не было условий гонки, если несколько клиентов пишут в UART. - person Paebbels; 22.01.2015

Теперь мы решили проблему наполовину, используя pppd. Оказывается, даже Windows поддерживает ppp. В отличие от socat, pppd фактически использует протокол, в который будет включено обнаружение ошибок, и он автоматически создает сетевые устройства в системах Linux и Windows.

Единственная проблема в том, что pppd требует доступа к последовательному устройству. Нет прямого режима, который предоставляет инструмент ppp.

Теперь мы отключаем оболочку по требованию, перезагружаясь в режим IP-over-serial. Когда мы закончим, мы перезагрузим систему, которая автоматически переключится обратно на getty, используя последовательную линию.

Это не самое красивое решение, но сейчас оно, кажется, работает.

person jaw    schedule 28.01.2015