Внедряване на UDP прокси

Опитвам се да създам прости TCP и UDP проксита. Няма проблем с TCP проксито, но UDP е малко по-сложен за работа. Класическият прокси сценарий би бил така.

  1. Слушайте за входящи пакети от клиенти
  2. Когато пакетът бъде получен, той се изпраща до местоназначението (сървър)
  3. Слушайте за възможни пакети с отговор от сървъра
  4. Изпратете пакети с отговори обратно на клиентите

Добре, това трябва да е просто. Но когато се опитвам да приложа това с помощта на Synapse или Indy, имам проблем. когато получа пакет от клиент, правя вътрешен UDP клиент, за да препратя пакета до дестинацията. След това трябва да изслушам възможните отговори от дестинацията. Сега въпросът е коя е най-добрата реализация за това? Няма единична заявка/отговор като в TCP. Дестинацията може да отговори с няколко отговора с течение на времето или изобщо да не отговори. Ако продължа да слушам за отговор на един клиентски пакет, тогава ще пропусна други бъдещи пакети от този или други клиенти.

Търся добър дизайн за този проблем. Ето примерна комуникация за справка. Обърнете внимание на множеството отговори от дестинацията в един момент

- bind UDP port 40222 on interface 0.0.0.0
- ready
- add 127.0.0.1:4569

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 00 00 00 00 00 03 00 00 06 01 0b 02 00 02   ................
02 0a 37 30 30 35 35 35 31 32 31 32 04 0d 4e 6f   ..7005551212..No
74 20 41 76 61 69 6c 61 62 6c 65 09 04 00 00 00   t Available.....
08 08 04 00 00 00 08 06 06 31 36 31 34 30 31 01   .........161401.
08 34 31 33 31 33 39 34 37 0d 08 34 31 33 31 33   .41313947..41313
39 34 37                                          947

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 00 09 00 01 06 08 0e 02 00 03   ..C.............
0f 09 34 31 38 32 32 31 37 38 33 06 06 31 36 31   ..418221783..161
34 30 31                                          401

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 29 e7 00 00 00 4f 01 01 06 09 10 20 39 36   ..)....O..... 96
64 66 37 31 32 38 61 62 35 39 39 37 65 36 37 36   df7128ab5997e676
65 62 38 63 61 30 33 39 38 66 33 34 30 65         eb8ca0398f340e

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 00 56 01 02 06 07 09 04 00 00   ..C....V........
00 08                                             ..

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 29 e7 00 00 00 56 02 02 06 04               ..)....V....

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 02 85 02 02 04 0e               ..C.........

192.168.90.10:4569 -> 127.0.0.1:4569
a9 e7 43 ef 00 00 02 96 03 02 02 08 54 54 54 54   ..C.........TTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54               TTTTTTTTTTTT

127.0.0.1:4569 -> 192.168.90.10:4569
c3 ef 29 e7 00 00 02 96 02 04 06 04               ..).........

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 aa 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 be 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 d2 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 e6 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

192.168.90.10:4569 -> 127.0.0.1:4569
29 e7 02 fa 54 54 54 54 54 54 54 54 54 54 54 54   )...TTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54 54 54 54 54 54 54 54 54 54 54 54 54   TTTTTTTTTTTTTTTT
54 54 54 54                                       TTTT

РЕДАКТИРАНЕ:

За протокола. Може би UDP проксито е твърде объркан за внедряване, за да може да се използва. Това е голяма вероятност, но теоретично със сигурност е изпълнимо. Но ще опитам просто за удоволствие. Ако получа стабилно работещо решение, още по-добре. Иначе ще науча нещо ново и ще се призная за победен.

В никакъв случай не се опитвам да проявявам инат и да влизам с главата през стената. Все още се надявам някой да има добра идея :)


person Runner    schedule 23.03.2011    source източник
comment
Само забележка - TCP също не е протокол за заявка/отговор. Можете да изпратите нещо и да не получите нищо в отговор. Това вероятно е протокол на ниво приложение, с който дебъгвате вашия прокси, който е заявка/отговор.   -  person Eugene Mayevski 'Callback    schedule 23.03.2011
comment
Да, съгласен съм, но ако не получите нищо обратно, тогава знаете, че няма отговор. За разлика от UDP, където можете да получите отговор след минута закъснение.   -  person Runner    schedule 23.03.2011
comment
Не мога да се съглася с вас тук - TCP също не дава редовни отговори. Никога не знаете кога сървърът отговаря. Обикновено страните (най-вече клиентите) на протоколите на ниво приложение (като FTP) имат отделна стойност за изчакване, обикновено 60-120 секунди. Така че отново TCP и UDP са на една и съща позиция тук.   -  person Eugene Mayevski 'Callback    schedule 23.03.2011


Отговори (2)


Не само прокситата имат този проблем с UDP - мрежови устройства като защитни стени с проследяване на състоянието и NAT устройства също се сблъскват с него.

Типичният начин, по който се работи, е да има изчакване. След като не бъде наблюдаван UDP трафик между прокси клиента и сървъра за времето на изчакване, „връзката“ се прекъсва. Когато се види трафик, времето за изчакване се нулира.

Освен това наличието на една текуща прокси връзка не трябва да пречи на друга да бъде отворена едновременно - вашият прокси трябва да може да се справи с това.

person caf    schedule 23.03.2011
comment
Да, стигнах до абсолютно същото заключение :) Нов вътрешен клиент от група клиенти за всеки нов пакет. След това слушайте за отговор за определен период от време и след това освободете клиента. Все пак може да има проблем с броя на свободните портове. - person Runner; 23.03.2011
comment
Точно затова казвам, че общо решение не е възможно. Имах късмет/нещастието да се справя с много SIP трафик, това е UDP и Linux iptables за NAT: Iptables може да се справи, но има специфичен модул за проследяване на SIP протокола ! Не казвам, че не може да се направи, ако момчетата от iptables не са го направили, но е добър знак, че ще бъде трудно. - person Cosmin Prund; 23.03.2011
comment
@Cosmin Prund, Да, сигурен съм, че е трудно. Но това го прави още по-интересно за мен :) Пакетите, показани във въпроса ми, принадлежат към IAX протокол. Това е другият протокол, освен SIP, който Asterisk VOIP поддържа. Ето защо искам да опитам и да го направя. Ако се проваля, няма да има вреда. - person Runner; 23.03.2011
comment
@Runner, колкото си струва, IAX е по-лесен за NAT, отколкото за SIP, вероятно по-лесен за прокси. Забавлявай се! - person Cosmin Prund; 23.03.2011

Типичната UDP комуникация клиент-сървър може да изглежда така:

  • Клиентът изпраща UDP пакет към порт 1000
  • Сървърът получава пакет и изпраща обратно отговор към порт 1001 (или порт 1000!)

Вашият прокси трябва просто да слуша пакети както на порт 1000, така и на 1001. Когато пакет влезе на порт 1000, изпратете го на порт 1000 на сървъра. Когато пакет пристигне на порт 1001, той е от сървъра и трябва да бъде изпратен на порт 1001 до съответния клиент. Това е почти мястото, където забавлението свършва. UDP не предлага нищо по отношение на управление на сесия или връзка: Всичко зависи от конкретния UDP протокол, който се опитвате да проксиирате. Ако сте получили UDP пакети от 2 различни клиента и получите пакет "отговор" от сървъра, в самия UDP няма нищо, което да ви каже къде да препратите този пакет. Протоколите, изградени върху UDP, може или не могат да имат някакъв начин за поддържане на състоянието.

Генерично решение не е възможно, трябва да прочетете RFC и да внедрите специфични помощници за всеки един UDP протокол, който искате да поддържате.

person Cosmin Prund    schedule 23.03.2011
comment
Смята се, че е възможно общо решение. Мога да имам клиентски пул и всеки клиент да се обвърже към различен вътрешен порт. Но проблемът е, че може да ми свършат портовете или да се свържа с вече свързани портове. Да, UDP би трябвало да е прост, но прави внедряването на прокси адски. Сега знам защо SSH тунелирането поддържа само TCP. :) Надявам се някой да има брилянтно и просто решение :) - person Runner; 23.03.2011
comment
Да приемем, че решите да се свържете към портове 6000-6099, за да обработите 100 различни клиента. Как да убедите клиент 1 да изпрати до 6000 и клиент 2 да изпрати до 6001, когато и двата клиента биха предпочели да изпратят до порт 1000, тъй като това е в RFC за протокола, който се внедрява през UDP? - person Cosmin Prund; 23.03.2011
comment
Ако имате едно приложение, което искате да прокси, стартирате проксито и слушате на порт 6000 например. Приложението се свързва с localhost на порт 6000. За всеки пакет, който проксито получава, той вътрешно създава UDP клиент на нов порт и изпраща данните до дестинацията. след това слуша за отговори за определен период от време. Винаги имате един локален порт, на който слушате, и единична дестинация IP/порт. Ако имате нужда от повече, стартирайте повече проксита на различни портове. - person Runner; 23.03.2011
comment
Тествах такова решение, така че знам, че е възможно. linux.softpedia.com/get/Internet/ Прокси/ - person Runner; 23.03.2011
comment
И не, не мога да използвам това, защото бих искал да има криптиране между два такива проксита :) - person Runner; 23.03.2011