Назад | Перейти на главную страницу

Как настроить постоянный TCP-прокси для смены пола?

У меня есть провайдер (A), который хочет отправлять нам данные через входящее TCP-соединение. К сожалению, служба-получатель (B) не может принимать входящие TCP-соединения. Также у него нет статического IP-адреса, еще одно требование.

Одним из способов решения этой проблемы является служба, которая соединяет входящий порт TCP A с другим портом TCP B, чтобы потребитель мог установить исходящее соединение с B.

Это не уникальная проблема [1] [2], а с socat я могу сделать что-то очень близкое к тому, что хочу:

socat -d -d -d -u TCP4-LISTEN:PORT-A,reuseaddr TCP4-LISTEN:PORT-B,reuseaddr

Однако при этом возникают следующие проблемы:

Есть ли способ настроить команду таким образом, чтобы она стала «постоянной» и устойчивой к сбоям?

Важный вопрос: как A отреагирует на потерю соединения или на отказ в соединении? Все, что предполагает, что одно TCP-соединение будет работать вечно, будет хрупким; такова природа Интернета.

Как насчет настройки socat как [x]inetd служба?

Вы бы установили xinetd для прослушивания в PORT-B, и запустить socat -u TCP4-LISTEN:PORT-A,reuseaddr STDIO как только сторона B подключится.

xinetd будет передавать входящий трафик со стороны B на стандартный ввод socat, и поймать стандартный вывод socat и передайте его стороне B.

Если B отключается, то socat процессу можно дать закончиться; xinetd начнет новый, как только B снова подключится. Пока B отключен, A будет получать сообщения об ошибке «соединение отклонено».

Однажды мне пришлось сделать нечто подобное на старой системе HP-UX.

Реальный мир запутан.

В реальном мире иногда TCP-соединения умирают, это может произойти, например, если перезагружается межсетевой экран с отслеживанием состояния или NAT, если соединение идет слишком долго без трафика, если базовое соединение слишком долго не работает.

Кроме того, иногда, когда соединения умирают, они умирают не симметрично. Если соединение, передающее много данных, умирает, вероятно, отправитель заметит, что оно не работает, задолго до того, как это сделает получатель. У этого есть пара побочных эффектов.

  • Если соединение инициируется от отправителя к получателю, тогда может появиться новое соединение, в то время как старое соединение, очевидно, все еще живо.
  • Если соединение инициируется от получателя к отправителю, то может быть значительная задержка между обнаружением отправителем разрыва соединения и обнаружением этого факта получателем и запуском повторного соединения.

Кроме того, TCP-соединения представляют собой поток байтов, а НЕ поток сообщений, поэтому, когда ваше соединение умирает, вы можете получить частичное сообщение.

Конечный результат этого приводит меня к выводу, что надежное решение требует понимания протокола приложения, чтобы ваше решение могло его понять.

  1. Как объединить потоки при новом подключении.
  2. Следует ли сохранять сообщения, когда источник данных подключается получателем данных, - нет.
  3. Подходит ли механизм сквозного подтверждения для предотвращения потери сообщения.
  4. Требуется ли какой-то механизм «ping» на уровне приложения для ускорения обнаружения мертвых соединений.