В настоящее время я настраиваю IPtables для перенаправления определенных полезных данных UDP в свое приложение.
Вот пример того, над чем я работал до сих пор:
iptables -t nat -I PREROUTING -p udp -d {IPDST} --dport 27055 -m u32 --u32 '0>>22&0x3C@8=0xFFFFFFFF && 0>>22&0x3C@12=0x54536F75 && 0>>22&0x3C@16=0x72636520 && 0>>22&0x3C@20=0x456E6769 && 0>>22&0x3C@24=0x6E652051 && 0>>22&0x3C@28=0x75657279' -j REDIRECT --to-port 21015
Это работает, он перенаправит пакеты, содержащие полезную нагрузку:
FFFFFFFF54536F7572636520456E67696E6520517565727900
с одного порта на мое приложение на другом.
Проблема в том, что у меня есть еще один фрагмент данных, который я хочу перенаправить, но он не всегда один и тот же. Пакет выглядит так:
ffffffff55ffffffff
Однако иногда пакет может выглядеть так:
ffffffff55fa0cf40f
Я пробовал что-то вроде этого:
iptables -t nat -I PREROUTING -p udp -d {IPDST} --dport 27055 -m u32 --u32 '0>>22&0x3C@8=0xFFFFFFFF && 0>>22&0x3C@12=0x55' -j REDIRECT --to-port 21015
Я предполагаю, что проблема в том, что я пытаюсь сопоставить 2 байта, а не 4, как обычно? Вышеупомянутое не является ошибкой, но также не перенаправляет пакеты.
Это было бы для вашего удобства (в одну строку, но мне пришлось отобразить это так, чтобы работать жирным шрифтом):
iptables -t nat -I PREROUTING -p udp -d {IPDST} --dport 27055 -m u32 --u32 '0>>22&0x3C@8=0xFFFFFFFF && 0>>22&0x3C@12
>>24
=0x55' -j REDIRECT --to-port 21015
или
iptables -t nat -I PREROUTING -p udp -d {IPDST} --dport 27055 -m u32 --u32 '0>>22&0x3C@8=0xFFFFFFFF && 0>>22&0x3C@12
&0xFF000000=0x55000000
' -j REDIRECT --to-port 21015
В обоих случаях вы удаляете из уравнения ту часть, которую не хотите сравнивать, либо сдвигая 3 байта вправо и оставляя только 1-й, либо используя маску, которая сохранит в уравнении только 1-й байт. Второй более гибкий.
Есть пример в man iptables-extensions
аналогично первому варианту:
... 0 >> 22 & 0x3C @ 0 >> 24 = 0 "
[...]
Это первые 4 байта полезной нагрузки ICMP, из которых байт 0 является типом ICMP. Поэтому мы просто сдвигаем значение 24 вправо, чтобы отбросить все, кроме первого байта, и сравнить результат с 0.
Также обратите внимание, что, поскольку это таблица nat, если порт источника не меняется, будет рассматриваться только первый пакет UDP. После этого conntrack будет обрабатывать поток, и ваше правило не увидит другие пакеты. Поэтому, если каждый пакет независим, убедитесь, что исходный порт изменился, и вам, возможно, придется использовать nfct
инструмент вместе с -j CT --timeout
правило, чтобы сократить "память" conntrack и избежать заполнения его таблиц.