Как туннелировать TCP через надежный UDP? - PullRequest
7 голосов
/ 14 декабря 2009

Предположим, у меня есть надежная библиотека UDP, и я хочу туннелировать произвольные TCP-соединения через нее. Это мой текущий подход к этому, но я чувствую, что он может быть не очень эффективным. Любые предложения приветствуются.

  1. Клиент устанавливает надежное UDP-соединение с сервером.
  2. Клиент запускает локальный прокси-сервер SOCKS5, который получает данные от любого приложения, которое подключается к нему, и пересылает его через надежное соединение UDP. Каждый пакет содержит 4-байтовый идентификатор, уникальный для каждого соединения SOCKS.
  3. Сервер получает данные. Если 4-байтовый идентификатор является новым, он устанавливает новое соединение с локальным TCP-сокетом и отправляет данные, а также создает новый поток, который получает любые ответы от сервера и перенаправляет их через надежное соединение UDP с соответствующим идентификатором. Если 4-байтовый идентификатор старый, он просто отправляет данные по существующему TCP-соединению.
  4. Клиент получает данные, отправляя их по существующему соединению SOCKS любому приложению, в котором они были запущены.

Сейчас кажется, что это работает для выполнения простых запросов HTML из браузера, но поскольку сервер не подключен напрямую к клиенту, он не может определить, когда клиент завершает соединение. Есть ли лучший способ сделать это?

РЕДАКТИРОВАТЬ: Нет, это не домашнее задание. И, пожалуйста, не беспокойтесь об ответах, если вы не знаете о преимуществах надежных библиотек UDP или даже не слышали о них раньше. Спасибо.

Ответы [ 3 ]

9 голосов
/ 14 декабря 2009

есть несколько готовых опций:

  • OpenVPN : туннелирование фреймов IP или Ethernet поверх UDP
  • Teredo : туннелирует IPv6 поверх UDPv4, управляет как обходом NAT, так и полной совместимостью с IPv6
  • UDT : нестандартный, надежный, высокопроизводительный, мульти-транспортный, TCP-подобный протокол поверх UDP. Опционально позволяет вам управлять прохождением NAT, а затем берет его оттуда
0 голосов
/ 15 декабря 2009

Вам нужно будет сообщить о потере клиентского TCP-соединения на стороне сервера через ваш UDP-туннель (и наоборот, если сервер должен сначала закрыть соединение).

В противном случае, помимо того, что HTTP-сервер не знает, что клиент отключился, вы будете пропускать соединения на стороне, которая не инициировала закрытие соединения.

Один из способов сделать это - зарезервировать специальное значение вашего 32-битного поля идентификатора соединения - скажем, 0x00000000 или 0xffffffff - как представление контрольного пакета, а не данных соединения. Далее следует еще одно 4-байтовое поле, представляющее идентификатор соединения, а за ним - поле кода операции. Первый код операции, который вы можете определить, это «Соединение разорвано».

  • Если ваша клиентская часть туннеля обнаруживает, что клиентское приложение закрыло свое TCP-соединение, она отправляет пакет с завершением соединения для соответствующего идентификатора соединения через туннель;
  • Если ваша клиентская часть туннеля получает код операции «Соединение разорвано» со стороны сервера, то она закрывает соединение с клиентским приложением;

и аналогичные для серверной части туннеля.

0 голосов
/ 14 декабря 2009

Самый эффективный способ - это когда две конечные точки напрямую общаются друг с другом. Если они взаимодействуют с разными протоколами, вам нужен как минимум один прокси / шлюз / преобразователь трафика / что угодно. В этом случае нет возможности обойти два из этих преобразователей, так как теперь у вас есть 3 вовлеченных компонента: клиент конечной точки, сетевой трафик, сервер конечной точки. Я не понимаю, как вы могли бы сделать его более эффективным в данных обстоятельствах.

Что касается разорванных соединений, если вы используете туннель, то используйте его для всего трафика, то есть для передачи всех видов запросов как клиента, так и сервера другой стороне. Если завершение не может быть сообщено серверу, то проблема находится на стороне клиента - конечная точка клиента не сообщает свое завершение входу в туннель клиента. Если это так, то вы можете передать это завершение на сервер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...