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

Маршрутизация TCP-пакетов на локальный UDP-порт

Сторонний сервер отправляет UDP-пакеты в настроенный нами экземпляр EC2, и я пытаюсь направить эти пакеты на свой локальный компьютер.

Клиент отправляет эти пакеты на порт 8975

Для этого я сначала установил ssh-туннель к моему экземпляру ec2.

ssh -4 -L 10000:localhost:10000 -i ~/.ssh/xxxx.pem ubuntu@13.xxx.x.xx

на моем удаленном компьютере - я перенаправил пакеты, полученные на порт 8975, на 10000, используя эту команду

netcat -l -u -p 8975 > /tmp/udp2tcp | netcat -l -p 10000 < /tmp/udp2tcp

udp2tcp это файл FIFO

на моем локальном компьютере - я беру tcp пакеты, которые я получаю, и конвертирую их обратно в UDP

netcat localhost 10000 > /tmp/tcp2udp | netcat -l -u -p 8975 < /tmp/tcp2udp

Когда я бегу netcat localhost 10000 - я вижу поток пакетов на моем локальном компьютере

но по какой-то причине пакеты не маршрутизируются как udp на порт 8975 - я не уверен, что именно мне нужно делать

когда я бегу sudo tcpdump -i any -S -vvv port 10000

Это показывает мне, что пакеты попадают в

15:39:10.053013 IP (tos 0x0, ttl 64, id 64725, offset 0, flags [DF], proto TCP (6), length 52)
    localhost.48974 > localhost.webmin: Flags [.], cksum 0xfe28 (incorrect -> 0x5674), ack 1261213200, win 10567, options [nop,nop,TS val 1064223053 ecr 1064223053], length 0

но когда я запускаю sudo tcpdump -i any -S -v port 8975 - я ничего не вижу

В качестве альтернативы переадресации портов SSH вы можете пересылать эти UDP-пакеты на свой локальный компьютер с помощью туннельных устройств точка-точка, SSH и процедуры, описанной ниже.

В экземпляре EC2 сделайте следующее:

  1. В /etc/ssh/sshd_config файл, установить параметр конфигурации PermitTunnel либо point-to-point или yes.

  2. Создайте туннельное устройство точка-точка, которое будет получать пакеты UDP из общедоступной сети:

    $ sudo ip tuntap add dev tun8975 mode tun user ubuntu
    $ sudo ip addr add dev tun8975 172.16.19.22 peer 172.16.19.21
    $ sudo ip link set dev tun8975 up
    
  3. Настройте IPTABLES или NFTABLES для пересылки таких UDP-пакетов на туннельное устройство.

    $ sudo iptables -t nat -A PREROUTING '!' -i tun8975 -p udp --dport 8975 -j DNAT --to-destination 172.16.19.21:8975
    
    $ sudo nft add rule ip nat PREROUTING iifname '!=' "tun8975" udp dport 8975 dnat to 172.16.19.21:8975
    
  4. Убедитесь, что ядро ​​разрешает пересылку IP-пакетов между сетевыми интерфейсами:

    $ sudo sysctl -w net.ipv4.ip_forward=1
    

После этого на вашем локальном компьютере сделайте следующее:

  1. Создайте туннельное устройство точка-точка, которое SSH будет использовать для вывода перенаправленных пакетов UDP:

    $ sudo ip tuntap add dev tun8975 mode tun
    $ sudo ip addr add dev tun8975 172.16.19.21 peer 172.16.19.22
    $ sudo ip link set dev tun8975 up
    
  2. Запросите SSH для пересылки трафика между туннельными устройствами через защищенный канал:

    $ sudo ssh -4 -o Tunnel=point-to-point -w 8975:8975 -i ~/.ssh/xxxx.pem ubuntu@13.xxx.x.xx
    

Я вижу две проблемы в вашем подходе к решению проблемы коммуникации.

Первая проблема заключается в запуске команды на локальном компьютере. Я считаю, что -l флаг на UDP-части netcat командный конвейер должен быть удален, а другой процесс на вашем локальном компьютере (который может быть другим netcat) должен прослушивать UDP-порт 8975 и получать датаграммы, отправленные на этот порт. netcat в этом сценарии будет работать в клиентском режиме и генерировать такие датаграммы.

Вторая проблема заключается в том, как создаются эти командные строки:

  • На удаленной машине
    $ netcat -l -u -p 8975 > /tmp/udp2tcp | netcat -l -p 10000 < /tmp/udp2tcp
    
  • На локальной машине
    $ netcat localhost 10000 > /tmp/tcp2udp | netcat -l -u -p 8975 < /tmp/tcp2udp
    

Они смешивают перенаправления и конвейеры. Хотя я читал Трубопроводы и Перенаправление разделы из Страница руководства Bash и выяснил, что конвейеры будут обрабатываться до перенаправления, я не могу понять, как оболочка будет соединять стандартные потоки с использованием такого синтаксиса.

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

Возможно, командные строки, которые вы используете, уже достигают этой цели. Несмотря на это, я предлагаю более явную пересылку данных с помощью следующих команд:

  • На удаленной машине

    $ cat /tmp/udp2tcp | netcat -l -u -p 8975 | netcat -l -p 10000 > /tmp/udp2tcp
    
  • На локальной машине

    $ cat /tmp/tcp2udp | netcat localhost 10000 | netcat -u localhost 8975 > /tmp/tcp2udp
    

В обоих случаях первым подключается анонимный канал. netcatSTDOUT в секунду netcatSTDIN и именованный канал (fifo) будут подключать второй netcatSTDOUT назад к первому netcatSTDIN.

Рассмотрите возможность обучения netcat использовать только стек IPv4, добавив -4 флаг для аргументов командной строки. Это может помочь, если процесс, прослушивающий UDP-порт 8975, несовместим с IPv6.