Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Алгоритм определения сервера в TCP пакете  (Прочитано 24393 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« : 08-06-2010 15:32 » 

Столкнулся с интересной задачей. Есть TCP пакет, необходимо определить от кого пришел данный пакет, от сервера или клиента в клиент-серверном TCP соединении. То есть, надо понять какой порт, dst_port или src_port, в TCP пакете принадлежит серверной стороне.

Конечно со сто процентной вероятностью нельзя сказать от кого идет пакет, от сервера или от клиента в TCP соединении, но с некоторой долей вероятности такие предположения делать можно. Сейчас реализован довольно простой алгоритм:

Код:
...

#ifndef IPPORT_RESERVED
#define IPPORT_RESERVED 1024
#endif
#ifndef IPPORT_USERRESERVED
#define IPPORT_USERRESERVED 5000
#endif
#ifndef IPPORT_HIFIRSTAUTO
#define IPPORT_HIFIRSTAUTO  49152
#endif
#ifndef IPPORT_HILASTAUTO
#define IPPORT_HILASTAUTO 65535
#endif

...

static u_char s_port_big[IPPORT_RESERVED];

#define CHECK_SRV(p, proto) (s_port_big[(p) & (IPPORT_RESERVED-1)] & (proto))
#if IPPORT_HILASTAUTO < USHRT_MAX
#define IS_USER_PORT(p) (((p) >= IPPORT_RESERVED && (p) < IPPORT_USERRESERVED) || \
  ((p) >= IPPORT_HIFIRSTAUTO && \
  (p) <= IPPORT_HILASTAUTO))
#else
/* (p) <= IPPORT_HILASTAUTO is always true because (p) is an unsigned short */
#define IS_USER_PORT(p) (((p) >= IPPORT_RESERVED && (p) < IPPORT_USERRESERVED) || \
  ((p) >= IPPORT_HIFIRSTAUTO))
#endif

...

  setservent(1);
  while ((sv = getservent())) {
    NTOHS(sv->s_port);
    if (sv->s_port >= IPPORT_RESERVED) {
      i = sv->s_port & (IPPORT_RESERVED-1);
      if (strcmp(sv->s_proto, "tcp") == 0)
        s_port_big[i] |= IPPROTO_TCP;
      else if (strcmp(sv->s_proto, "udp") == 0)
        s_port_big[i] |= IPPROTO_UDP;
    }
  }
  endservent();

...

  t.p_port = min(tp->th_sport, tp->th_dport);
  if (t.p_port < IPPORT_RESERVED ||
    (IS_USER_PORT(tp->th_sport) && IS_USER_PORT(tp->th_dport))) {
    t.who_srv = tp->th_sport < tp->th_dport ? 1 : 2;
  }
  else if (tp->th_sport == tp->th_dport) {
    t.who_srv = 3;
  }
  /* tp->th_sport > IPPORT_RESERVED && tp->th_dport > IPPORT_RESERVED */
  else {
    if (CHECK_SRV(tp->th_sport, IPPROTO_TCP)) {
      t.who_srv = 1;
    }
    else if (CHECK_SRV(tp->th_dport, IPPROTO_TCP)) {
      t.who_srv = 2;
    }
    else {
      t.who_srv = !IS_USER_PORT(tp->th_sport) ? 1 : 2 ;
    }
    t.p_port = (t.who_srv == 2 ? tp->th_dport : tp->th_sport);
  }

...

Если описать словами в двух словах то работает это так:

1. Заполняется массив s_port_big значениями соответствующими истине в соответствии с описанием зарегистрированных в IANA (/etc/services) службами. Далее этот массив используется в спорных случаях для проверки того, что порт принадлежит одной из зарегистрированных в IANA службе (серверу).
Цитата
Тут есть одна бага, массив определяется для 1024 значений (s_port_big[IPPORT_RESERVED]) но данные в него заносятся для 65535 вариантов. Хотя и не происходит выход за пределы массива, но он начинает содержать в некоторых случаях истинные значения для не зарегистрированных служб.

2. Если один из минимальных портов принадлежит диапазону меньшему чем 1024, то считается что этот порт принадлежит серверу.

3. Если оба порта находятся в диапазоне большем или равном чем 1024 и меньшем чем 5000 или большем или равном 49152 (так называемый диапазон клиентских портов) то выбирается самый меньший порт и считается что он принадлежит серверу.

4. Если оба порта одинаковы, то тут нельзя сказать от кого идет пакет, от сервера или клиента.

5. Проверяется что src_port принадлежит одной из служб в s_port_big, если это так то это сервер.

6. Проверяется что dst_port принадлежит одной из служб в s_port_big, если это так то это сервер.

7. И последнее, проверяется что src_port не принадлежит диапазону клиентских портов, если это так то это порт сервера, иначе dst_port порт сервера.

Конечно это не самый идеальный алгоритм. Поэтому я и советуюсь, может есть более лучший алгоритм, который будет работать с более высокой вероятностью определения порта сервера?.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 08-06-2010 16:30 » 

Serg79,

0. Наверно таки пакет IP+TCP? Улыбаюсь

1. Какая у тебя среда и ОС?

2. В твоей задаче не известны адреса клиентов?

100% определить, кто сервер, а кто клиент можно только по любому из первых трех пакетов handshake.
« Последнее редактирование: 08-06-2010 16:34 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 08-06-2010 16:37 » 

Ну да IP+TCP, но я говорю про TCP-заголовок в котором определены порты отправителя и получателя.
Пакет может захватиться от любой машины с любой ОС.
Адреса клиентов заранее не известны.

Нужно придумать алгоритм, который бы с большой долей вероятности выдавал бы правильное решение.))
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 08-06-2010 16:41 » 

Адреса портов ниже 1024 это однозначно серверные порта. Насколько я знаю, клиентские порта биндится по умолчанию всегда больше 32768.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 08-06-2010 16:44 » 

В том то и дело что не всегда выше 32768, Windows начинает раздавать клиентские поры начиная от 1024 и заканчивая 5000 (по моему где то так).
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 08-06-2010 16:46 » 

Чуть чуть соврал http://ru.wikipedia.org/wiki/Зарезервированные_порты_TCP/UDP
Цитата
Для системных и некоторых популярных программ выделены общепринятые порты с номерами от 0 до 1023, называемые привилегированными или зарезервированными.
Порты с номерами 1024 — 49151 называются зарегистрированными портами.
Порты с номерами 49151 — 65535 называются динамическими портами.
Т.е. для клиенской части будет по умолчанию выделяться диапозон 49151 — 65535
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 08-06-2010 16:47 » 

0. Таки у тебя полный комплект или только TCP-часть?

1. Я имею в виду среду и ОС для твоей программы.

2. Одинаково ли мы понимаем?
 Сервер — хост, открывший слушающий порт.
 Клиент — хост, инициировавший соединение.

Можно с уверенностью сказать, что для TCP все первые 1023 порта, кроме 20 - серверные. Вероятность, что их использует клиент — практически нулевая. Остальные — вероятнее всего клиентские. Перебирать все возможные службы из диапазона 1024..65535 — гадание на кофейной гуще. Но, если на один и тот же хост на один и тот же порт часто посылают пакеты с разных IP, то это явно серверный порт.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 08-06-2010 16:51 » 

Вить, не факт. У меня Win XP 64 начинает занимать с 1024 порта. Linux у меня по умолчанию использует 32768..61000. Если устанавливаю Oracle-сервер, то он требует, чтобы я указал ip_local_port_range 1024..64000.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 08-06-2010 16:54 » 

0. Пакет захватывается полностью, с ETH+IP+TCP (в зависимости от протокола).
1. Программа крутиться пот *NIX.
2. Да.

Ну да, с портами до 1024 все понятно. Запоминать частоту обращений к порту + IP накладно, наверно проще будет отслеживать SYN пакеты и уже вести данное соединение. Да, задача явно требует внесения модуля слежения за открытием и закрытием соединений, накладно получается все это.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #9 : 08-06-2010 16:58 » 

Ну для MS таблица портов http://support.microsoft.com/default.aspx?scid=kb;ru;832017#5
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 08-06-2010 17:11 » 

А такой еще вопрос. Ни кто не знает, можно как-нибудь по TCP пакету определить из какой системы он идет, может Windows добавляет какие то, свои специфические данные в дополнительные поля TCP заголовка?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #11 : 08-06-2010 17:16 » 

Сергей, я не думаю, все таки заголовок протокола строго стандартизирован. Но наверно можно смотреть на поля TTL,  превышение MTU.
« Последнее редактирование: 08-06-2010 17:18 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 08-06-2010 17:29 » 

Пакеты строго стандартные - никакой MS-специфики.
ОС определяют по переменным параметрам пакетов: последовательность выбора клиентских портов, характер смены идентификатора в заголовке IP, по динамике Sequence number и Acknowledgment number в заголовке TCP, по Window Size и т.п. косвенным признакам. Посмотри утилиту nmap - она умеет это делать.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 08-06-2010 17:39 » 

Слежение за пакетами не так сложно (в скобках — ответ противоположной стороны):
1. Последовательность SYN + (SYN/ACK) + ACK — старт соединения.
2. RST — односторонний сброс в любой момент.
3. FIN + (ACK) + (FIN) + ACK — согласованный сброс. Пара (ACK) + (FIN) может быть одним пакетом.
4. В случае физической невозможности послать завершение и "освободить канал", можно ждать по таймауту и еще сброс по SYN в этом же "канале".

http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Protocol_operation
« Последнее редактирование: 08-06-2010 17:41 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 08-06-2010 19:28 » 

http://kunegin.narod.ru/ref3/ataki/opr.htm
не вдавался в подробности

Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 08-06-2010 19:49 » 

Да не Sla, у меня снифится трафик и идет определение сервера в TCP пакете, выполнять какие то активные действия не нужно.

Нашел следующую информацию по диапазонам клиентских портов:
1025 - 5000 - до windows 2003
49152- 65535 - vista и 2008
49152 - 65535 - FreeBSD
32768 - 61000 - Linux
32768 - 65535 - Solaris

Но это настройки по умолчанию и при желании их можно изменить, но все равно на них попытаюсь завязаться.
« Последнее редактирование: 08-06-2010 20:09 от Serg79 » Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 08-06-2010 20:00 » 

Ни как не могу найти диапазон клиентских портов для Solaris, кто знает подскажите.
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 08-06-2010 20:09 » 

Нашел и для Solaris: 32768 - 65535
Записан
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 08-06-2010 20:13 » 

Кстати, заметил одну очень забавную вещь. В Linux как-то больше от Sys V чем от BSD.))
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 08-06-2010 21:11 » 

В Линукс быстрее смесь этих стилей. Но к портам это никакого отношения не имеет. Больше скажу, что в 2.4 (в более поздних ядрах не смотрел) был выбор диапазона в зависимости от объема памяти.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 09-06-2010 06:16 » 

Ну порты это только одно из немногих что мне бросилось в глаза. Сейчас я даже удивляюсь, почему в Linux не реализовали полную поддержку STREAMS от SVR4.))
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #21 : 09-06-2010 06:32 » new

Serg79, "зато у них негров линчуют" Ага В смысле, что Linux куда проще и понятней в управлении, чем Solaris.
Собственно, понять, что там таки поддерживается можно только просмотрев исходники (или хотя бы конфиг от исходников), а я к этому интерес давно потерял - мне хватает ядер дистрибутивной сборки, а в них, как правило, многое из специфичного  не включают.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines