Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Сети > Фильтр пакетов


Автор: XStrike 31.3.2006, 08:05
здравствуйте, вот не так давно появилась задача, надо сделать прогу, задать ейконкретный порт(по которому общается клиент с сервером), и заставить ее анализировать пакеты идущие ... ну и сделать пару правил по которым пакеты будут остановлены, и не дойдут до сервера...
пакеты в принципе я узнаю легко, сниффером ... порт так-же знаю ...

вопрос 1: как думаете? лучше такую программу цеплять на каждого клиента, или на сервер? как надежней?
вопрос 2: на каком языке лучше писать? (пишу в разделе Дельфи так как с ним лучше знаком)
вопрос 3: может у кого есть примеры подобных прог?

за ранее спасибо ..

Автор: Romikgy 31.3.2006, 09:06
Цитата(XStrike @ 31.3.2006, 07:05 Найти цитируемый пост)
вопрос 1: как думаете? лучше такую программу цеплять на каждого клиента, или на сервер? как надежней?

имхо на сервер, хотя для этих целей что-т типа файрвола делается

Цитата(XStrike @ 31.3.2006, 07:05 Найти цитируемый пост)
вопрос 2: на каком языке лучше писать? (пишу в разделе Дельфи так как с ним лучше знаком)


все равно

Цитата(XStrike @ 31.3.2006, 07:05 Найти цитируемый пост)
вопрос 3: может у кого есть примеры подобных прог?

у меня нет smile

Цитата(XStrike @ 31.3.2006, 07:05 Найти цитируемый пост)
за ранее спасибо ..

за ранее пожалуста , только правила на форум почитай надосуге smile

Автор: Snowy 31.3.2006, 09:15
Для этих целей отлично подходит TIdTCPMappedPort С закладки Indy Servers

Автор: XStrike 31.3.2006, 12:17
увы .. не нашел ... понимаю .... звучит туповато ... Snowy ... Link please smile

Автор: Snowy 31.3.2006, 12:32
Да какой тут линк.
Запускай дельфи. Найди закладку Indy Servers. Найди на най компонент IdMappedPortTCP.
Брось его на форму. Нажми F1. Читай хелп.

Посты по нему:
http://forum.vingrad.ru/index.php?showtopic=83150
http://forum.vingrad.ru/index.php?showtopic=78230&view=findpost&p=618877

Автор: XStrike 31.3.2006, 12:46
thanks огромное ... выручил чайника ... smile
кстати ... вопрос ... в связи с правилами ...
канал у меня не очень... форум довольно тяжко грузится ... Snowy ... разрешаешь аськой воспользоваться ???

Автор: Snowy 31.3.2006, 12:58
Вот код мапера.
Данный код просто протоколирует данные - скидывает все в файл.
Но вместо этого может и другие действия выполнять.
Код

type
  TForm1 = class(TForm)
    MAP: TIdMappedPortTCP;
    Button1: TButton;
    ePort: TEdit;
    eHost: TEdit;
    eFile: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure MAPOutboundData(AThread: TIdMappedPortThread);
    procedure MAPExecute(AThread: TIdMappedPortThread);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  fs:    TFileStream;
  ini:   TStringList;

implementation

{$R *.dfm}

const
  IniFile = 'Mapper.ini';
  cnHost  = 'Host';
  cnPort  = 'Port';
  cnFile  = 'LogFile';

procedure TForm1.Button1Click(Sender: TObject);
begin
  if MAP.Active then
  begin  // Выключить маппер
    MAP.Active := false;
    Button1.Caption := 'ON';
    fs.Free;
  end else begin // включить маппер
    MAP.MappedHost := eHost.Text;
    MAP.MappedPort := StrToInt(ePort.Text);
    fs := TFileStream.Create(eFile.Text, fmCreate); // открываем Log File
    MAP.Active := true;
    Button1.Caption := 'OFF';
  end;
end;

procedure TForm1.MAPOutboundData(AThread: TIdMappedPortThread);
begin // Исходящие пакеты
  fs.Write(#13#10'<<<<'#13#10,8); // пишем в лог маркер исходящих
  fs.Write(AThread.NetData[1], Length(AThread.NetData)); // пишем в лог данные
end;

procedure TForm1.MAPExecute(AThread: TIdMappedPortThread); 
begin // Входящие пакеты
  fs.Write(#13#10'>>>>'#13#10,8); // пишем в лог маркер входящих пакетов
  fs.Write(AThread.NetData[1], Length(AThread.NetData)); // пишем в лог данные
end;

function GetValue(Name, Def: string): string; // функция работы с ini файлом
begin
  result := ini.Values[Name];
  if result = '' then result := Def;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  inherited;
  ini := TStringList.Create; // подгрузить параметры из ini файла
  if FileExists(IniFile) then ini.LoadFromFile(IniFile);
  eHost.Text := GetValue(cnHost, eHost.Text);
  ePort.Text := GetValue(cnPort, ePort.Text);
  eFile.Text := GetValue(cnFile, eFile.Text);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ini.Values[cnHost] := eHost.Text; // сохранить параметры в ini файл
  ini.Values[cnPort] := ePort.Text;
  ini.Values[cnFile] := eFile.Text;
  ini.SaveToFile(IniFile);
end;

end.

Добавлено @ 13:03
Приаттачиваю полный проект

Автор: XStrike 31.3.2006, 14:53
еще вопрос ... будет ли маппер определять айпи адреса ... так как коннектов к серверу будет много (до двух сотен пользователей одновременно) ... принцип таков, заставлю его анализировать пакеты ... отслеживать надо будет только 2-4 из всех ... т.е. если проходит такой пакет, тогда в течении скажем 8-и секунд не пропускать на сервер такой-же пакет(заменять его другим, к примеру пакетом отключения от сервера, или просто "глушить" пакет ....) но ... пакет ведь идет прямо от клиента ... и если не сделать анализа по айпи ... программа будет обламывать всех юзеров ... а нужно только отправителя/получателя....

З.Ы. если кому интересно ... это античит для онлайн игрушки ...

Автор: Snowy 31.3.2006, 15:45
Цитата(XStrike @ 31.3.2006, 14:53 Найти цитируемый пост)
будет ли маппер определять айпи адреса
Конечно. Bindings есть у всех Indy серверов. В нем и найдешь IP:
AThread.Connection.Socket.PeerIP
Это и есть IP клиента.

Автор: XStrike 31.3.2006, 20:44
проект не полный ... не хватает .res файла ... пытался его скомпилировать ... не вышло ... говорит типа файл reconstructed ... но не появляется ...

Автор: XStrike 1.4.2006, 01:38
user posted image
user posted image
user posted image
user posted image

а вот и ошибки ... скрины ...

Автор: Snowy 1.4.2006, 10:21
Цитата(XStrike @ 31.3.2006, 20:44 Найти цитируемый пост)
проект не полный ... не хватает .res файла
А он и не нужен.

Цитата(XStrike @ 31.3.2006, 20:44 Найти цитируемый пост)
говорит типа файл reconstructed ... но не появляется ...
Нажми "сохранить" - появится.

Цитата(XStrike @ 1.4.2006, 01:38 Найти цитируемый пост)
а вот и ошибки
Под Delphi7 компилится без проблем.
Написан под Indy9. Для Indy10 код скорее всего будет другим.

Автор: XStrike 1.4.2006, 10:45
сохранял ... не появляется ... переписывал полностью - ничего .... видать дело в дельфи ... я в 6-м это делал ...
кстати ... может есть линк на апдейт ?

Автор: XStrike 2.4.2006, 00:49
Snowy, я достал 7-й дельфи и всё стало на место ... получил исполняемый файлик ...но беда в другом ... по идее должен идти лог пакетов идущих через указанный порт(ePort) ... но как бы не хотелось - файл постоянно пустой ....

как я понимаю, если вешать мапера на порт сервера(55901, так как именно сюда обращается клиент) то сам сервер нужно переводить на другой порт(ведь на 1 порт 2 процесса не повесить, так?) ... делал и это(вешал сервер на 55902, так как именно он используется SubServer'ом, если такой используется) ... но результ был вообще ужасный ... клиент не соединялся с сервером ...
Думаю дело в том что надо использовать в программке еще один порт, и на него пересылать данные одновременно с их записью в файл (хотя в будующем протоколирование заменю фильтрацией некоторых пакетов) ... но как бы я не старался ... перенаправить их на другой порт так и не получилось ... smile

пока удалось добавить ePort2, cnPort2 и оформить его в ini файл ...

Автор: Snowy 2.4.2006, 09:08
DefaultPort установи 55901
MappedPort - 55902
MappedHost - localhost
Клиенты должны цепляться на 55901 (DefaultPort)
Маппер будет все перенаправлять на 55902 (MappedPort) localhost'a.
Вероятно ты DefaultPort оставил 8080. Вот и не работает...
Я просто не выносил его в настройку, а сделал фиксированным.
Смени на нужный.

Автор: XStrike 2.4.2006, 23:36
Код

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdThreadMgr, IdThreadMgrDefault, IdBaseComponent,
  IdComponent, IdTCPServer, IdMappedPortTCP, ExtCtrls;

type
  TITMAPPER = class(TForm)
    PORTSGROUP: TGroupBox;
    MAPPEDPORT: TEdit;
    DEFAULTPORT: TEdit;
    LabelMP: TLabel;
    LabelDP: TLabel;
    HOSTSGROUP: TGroupBox;
    MAPPEDHOST: TEdit;
    LabelMH: TLabel;
    FILESGROUP: TGroupBox;
    FILENAME: TEdit;
    LabelMF: TLabel;
    MAP: TIdMappedPortTCP;
    IdThreadMgrDefault1: TIdThreadMgrDefault;
    Button1: TButton;
    EXITBUTTON: TButton;
    procedure EXITBUTTONClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure MAPOutboundData(AThread: TIdMappedPortThread);
    procedure MAPExecute(AThread: TIdMappedPortThread);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  ITMAPPER : TITMAPPER;
  FS       : TFileStream;
  Ini      : TStringList;


implementation

{$R *.dfm}

CONST
  IniFile='Mapper.ini';
  cnMAPPEDHOST='Host';
  cnMAPPEDPORT='Port';
  cnFILENAME='LogFile';
  cnDEFAULTPORT='DPort'; //constant for default port



procedure TITMAPPER.EXITBUTTONClick(Sender: TObject);
begin
CLOSE;
end;

procedure TITMAPPER.Button1Click(Sender: TObject);
begin
      IF MAP.Active THEN
        BEGIN //ShutDown Mapper
          MAP.Active := FALSE;
          DEFAULTPORT.Enabled :=TRUE;
          MAPPEDPORT.Enabled := TRUE;
          MAPPEDHOST.Enabled := TRUE;
          FILENAME.Enabled := TRUE;
          Button1.Caption := 'START';
          FS.Free;
        END
        ELSE
        BEGIN // Turn On Mapper
          MAP.MappedHost := MAPPEDHOST.Text;
          MAP.MappedPort := StrToInt(MAPPEDPORT.Text);
          MAP.DefaultPort := StrToInt(DEFAULTPORT.Text);
          FS := TFileStream.Create(FILENAME.Text, FMCreate); //Create&Open Log File
          DEFAULTPORT.Enabled := FALSE;
          MAPPEDPORT.Enabled := FALSE;
          MAPPEDHOST.Enabled := FALSE;
          FILENAME.Enabled := FALSE;
          MAP.Active := TRUE;
          Button1.Caption := 'STOP';
        END;

end;

procedure TITMAPPER.MAPOutboundData(AThread: TIdMappedPortThread);
begin //Outgoing Packets
        FS.Write(#13#10'<<<<<<'#13#10,8); //MARKER of OUTGOING PACKETS
        FS.Write(AThread.NetData[1], Length(AThread.NetData));
end;

procedure TITMAPPER.MAPExecute(AThread: TIdMappedPortThread);
begin //Outgoing Packets
        FS.Write(#13#10'>>>>>>'#13#10,8); //MARKER of OUTGOING PACKETS
        FS.Write(AThread.NetData[1], Length(AThread.NetData));
end;

function GetValue(Name, Def:String):String; //Work with ini
  BEGIN
    RESULT := ini.Values[Name];
    IF RESULT = '' THEN
      RESULT := Def;
  END;
procedure TITMAPPER.FormCreate(Sender: TObject);
  BEGIN
    INHERITED;
      ini := TStringList.Create; //Load From ini
      IF FileExists(iniFile) THEN
        ini.LoadFromFile(iniFile);
        MAPPEDHOST.Text  := GetValue(cnMAPPEDHOST, MAPPEDHOST.Text);
        MAPPEDPORT.Text  := GetValue(cnMAPPEDPORT, MAPPEDPORT.Text);
        DEFAULTPORT.Text := GetValue(cnDEFAULTPORT, DEFAULTPORT.Text);
        FILENAME.Text    := GetValue(cnFILENAME, FILENAME.Text);

  END;

procedure TITMAPPER.FormDestroy(Sender: TObject);
  BEGIN                               //Save to ini
      ini.Values[cnMAPPEDHOST] := MAPPEDHOST.Text;
      ini.Values[cnMAPPEDPORT] := MAPPEDPORT.Text;
      ini.Values[cnDEFAULTPORT] := DEFAULTPORT.Text;
      ini.Values[cnFILENAME] := FILENAME.Text;
      ini.SaveToFile(iniFile);
END;

end.


вот оно ... добавил настройку DefaultPort, немного видоизменил ... ну и конечно кнопка выключения smile
даже тестил на сервере ... протоколирует ... радует (даже учитывая лог размером в 5 кб за минуту, при одном юзере онлайнsmile ) ... еще раз спасибо Snowy smile
а далее требуется продолжение .... думаю будет это не проще чем до сих пор...

нужно к пакету приписывать айпи отправителя/получателя пакета (получатель - тот кому предназначен пакет идущий через сервер... но это не самое главное );

кстати ... если поймать пакет и получить его в HEX виде ... можно ли его обратно закодировать, и уже в таком виде запихнуть в программу как значение переменной/константы? .... ну а при проходе любого пакета сравнивать его с этой переменной/константой ... и при совпадении блокировать/перенаправлять/уничтожать ... ну в общем лучше начнем с айпи smile

Автор: Snowy 3.4.2006, 08:43
Цитата(XStrike @ 2.4.2006, 23:36 Найти цитируемый пост)
нужно к пакету приписывать айпи отправителя/получателя пакета (получатель - тот кому предназначен пакет идущий через сервер... но это не самое главное );
Ничего не ясно. Куда прописывать? Как узнать, кому адресован пакет? Что считать пакетом?


Цитата(XStrike @ 2.4.2006, 23:36 Найти цитируемый пост)
сли поймать пакет и получить его в HEX виде ... можно ли его  обратно закодировать, и уже в таком виде запихнуть в программу как значение переменной/константы? .... ну а при  проходе любого пакета сравнивать его с этой переменной/константой ...
Конечно можно.
Только поймать будет сложнее.
Это же сплошной поток. Начала пакета может придти отдельно, а хвост отдельно.

Автор: XStrike 3.4.2006, 11:02
Цитата

Ничего не ясно. Куда прописывать? Как узнать, кому адресован пакет? Что считать пакетом?


значит у нас есть 2 пользователя соединенных(П1 и П2) через сервер ...

П1 отправляет какой-то запрос П2 -> клиентП1 отправляет на сервер зашифрованый пакет, за тем сервер его обрабатывает и послыает другой пакет(с тем-же запросом но уже адресованый не серверу а клиенту) второму пользователю клиентуП2. Мапер конечно ловит оба пакета(так как они идут оба по одному порту) и вписывает их в лог, один как входящий а второй как исходящий, в логе мы имеем примерно это:

>>>>>>
{ВХОДЯЩИЙ ПАКЕТ}
<<<<<<
{ИСХОДЯЩИЙ ПАКЕТ}



для начала достаточно получить в ЛОГе такое :


>>>>>>
"IP ОТПРАВИТЕЛЯ ПАКЕТА НА СЕРВЕР"
{ВХОДЯЩИЙ ПАКЕТ}
<<<<<<
"IP ПОЛУЧАТЕЛЯ ПАКЕТА ОТ СЕРВЕРА"
{ИСХОДЯЩИЙ ПАКЕТ}


просто далее надо будет сделать в программе проверку след. типа :

ЕСЛИ ПОЛЬЗОВАТЕЛЮ(IP) ПОЛУЧИЛ/ОТПРАВИЛ ПАКЕТ С ЗАПРОСОМ ТО В ТЕЧЕНИИ 8-и СЕКУНД НЕ ПРОПУСКАТЬ К НЕМУ/ОТ НЕГО ПАКЕТОВ С ЗАПРОСАМИ .... а перевод в хекс нужен именно для определения тех-самых пакетов

Автор: Snowy 3.4.2006, 11:08
Код
s := #13#10'<<<<<<' + AThread.Connection.Socket.PeerIP + #13#10;
FS.Write(s[1], Length(s));

Автор: XStrike 3.4.2006, 11:48
немного конкретней ... как и куда это вписывать ?

Автор: Snowy 3.4.2006, 11:51
Вместо FS.Write(#13#10'<<<<<<'#13#10,8);
Аналогично с исходящими.

Автор: XStrike 14.4.2006, 10:56
Код

procedure TITMAPPER.MAPOutboundData(AThread: TIdMappedPortThread);
begin //Outgoing Packets
        s := #13#10'<<<<<<' + AThread.Connection.Socket.PeerIP + #13#10;
        FS.Write(s[1], Length(s)); //MARKER of OUTGOING PACKETS
        FS.Write(AThread.NetData[1], Length(AThread.NetData));
end;

в этом случае он не понимает что такое PeerIP(Undeclared Identifier : 'PeerIP') ... где его задать?

Автор: Snowy 14.4.2006, 11:10
Поправочка.
AThread.Connection.Socket.Binding.PeerIP
пропустил...

Автор: LeonW 4.2.2011, 12:03
Здравствуйте! написал я 
Код

procedure IdMappedPortTCP1MAPOutboundData(AThread: TIdMappedPortThread);
begin //Outgoing Packets
        s := #13#10'<<<<<<' + 'proba' + #13#10;
        FS.Write(s[1], Length(s)); //MARKER of OUTGOING PACKETS
        FS.Write(AThread.NetData[1], Length(AThread.NetData));
end;

но ответ на сервер приходит такой же как с клиента отправляю? 

Автор: Coobick 1.4.2011, 13:31
Всё это прекрасно... но как подобное сделать на новой инди? Не откатываться же на старую каждый раз..   smile 
Например как "переварить" эту строчку на инди 10?  smile 
Код

AThread.NetData:=ReplaceSub(AThread.NetData,'Referer: http://'+Edit1.Text+'/','Referer: http://'+Edit3.Text+'/');

(например в IdMappedPortTCP1Execute)
Сколько не гуглю всюду этот AThread..  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)