📄 main.pas
字号:
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, JSocket, WinSock, ExtCtrls, ComCtrls, Menus, IniFiles, GateShare;
const
GATEMAXSESSION = 10000;
type
TUserSession = record
Socket: TCustomWinSocket; //0x00
sRemoteIPaddr: string; //0x04
nSendMsgLen: Integer; //0x08
nReceiveMsgLen: Integer;
bo0C: Boolean; //0x0C
dw10Tick: LongWord; //0x10
nCheckSendLength: Integer; //0x14
boSendAvailable: Boolean; //0x18
boSendCheck: Boolean; //0x19
dwSendLockTimeOut: LongWord; //0x1C
n20: Integer; //0x20
dwUserTimeOutTick: LongWord; //0x24
SocketHandle: Integer; //0x28
sIP: string; //0x2C
MsgList: TStringList; //0x30
dwConnctCheckTick: LongWord; //连接数据传输空闲超时检测
dwReceiveTick: LongWord; //45AABC Tick
end;
pTUserSession = ^TUserSession;
TSessionArray = array[0..GATEMAXSESSION - 1] of TUserSession;
TFrmMain = class(TForm)
ServerSocket: TServerSocket;
MemoLog: TMemo;
SendTimer: TTimer;
ClientSocket: TClientSocket;
Panel: TPanel;
Timer: TTimer;
DecodeTimer: TTimer;
LbHold: TLabel;
LbLack: TLabel;
Label2: TLabel;
StatusBar: TStatusBar;
MainMenu: TMainMenu;
MENU_CONTROL: TMenuItem;
StartTimer: TTimer;
MENU_CONTROL_START: TMenuItem;
MENU_CONTROL_STOP: TMenuItem;
MENU_CONTROL_RECONNECT: TMenuItem;
MENU_CONTROL_CLEAELOG: TMenuItem;
MENU_CONTROL_EXIT: TMenuItem;
MENU_VIEW: TMenuItem;
MENU_VIEW_LOGMSG: TMenuItem;
MENU_OPTION: TMenuItem;
MENU_OPTION_GENERAL: TMenuItem;
MENU_OPTION_IPFILTER: TMenuItem;
H1: TMenuItem;
I1: TMenuItem;
procedure MemoLogChange(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure SendTimerTimer(Sender: TObject);
procedure TimerTimer(Sender: TObject);
procedure DecodeTimerTimer(Sender: TObject);
procedure ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket);
procedure ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
procedure ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure StartTimerTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure MENU_CONTROL_STARTClick(Sender: TObject);
procedure MENU_CONTROL_STOPClick(Sender: TObject);
procedure MENU_CONTROL_RECONNECTClick(Sender: TObject);
procedure MENU_CONTROL_CLEAELOGClick(Sender: TObject);
procedure MENU_CONTROL_EXITClick(Sender: TObject);
procedure MENU_VIEW_LOGMSGClick(Sender: TObject);
procedure MENU_OPTION_GENERALClick(Sender: TObject);
procedure MENU_OPTION_IPFILTERClick(Sender: TObject);
procedure I1Click(Sender: TObject);
private
dwShowMainLogTick: LongWord;
boShowLocked: Boolean;
TempLogList: TStringList;
nSessionCount: Integer;
StringList30C: TStringList;
dwSendKeepAliveTick: LongWord;
boServerReady: Boolean;
StringList318: TStringList;
dwDecodeMsgTime: LongWord;
dwReConnectServerTick: LongWord;
procedure ResUserSessionArray();
procedure StartService();
procedure StopService();
procedure LoadConfig();
procedure ShowLogMsg(boFlag: Boolean);
function IsBlockIP(sIPaddr: string): Boolean;
function IsConnLimited(sIPaddr: string): Boolean;
function AddAttackIP(sIPaddr: string): Boolean;
function CloseSocketAndGetIPAddr(nSocketHandle: Integer): string;
procedure CloseSocket(nSocketHandle: Integer);
function SendUserMsg(UserSession: pTUserSession; sSendMsg: string): Integer;
procedure ShowMainLogMsg;
procedure IniUserSessionArray;
{ Private declarations }
public
function AddBlockIP(sIPaddr: string): Integer;
function AddTempBlockIP(sIPaddr: string): Integer;
procedure CloseConnect(sIPaddr: string);
procedure MyMessage(var MsgData: TWmCopyData); message WM_COPYDATA;
{ Public declarations }
end;
procedure MainOutMessage(sMsg: string; nMsgLevel: Integer);
var
FrmMain: TFrmMain;
g_SessionArray: TSessionArray;
ClientSockeMsgList: TStringList;
sProcMsg: string;
implementation
uses HUtil32, GeneralConfig, IPaddrFilter, Grobal2;
{$R *.DFM}
procedure MainOutMessage(sMsg: string; nMsgLevel: Integer);
var
tMsg: string;
begin
try
CS_MainLog.Enter;
if nMsgLevel <= nShowLogLevel then begin
tMsg := '[' + TimeToStr(Now) + '] ' + sMsg;
MainLogMsgList.Add(tMsg);
end;
finally
CS_MainLog.Leave;
end;
end;
procedure TFrmMain.ServerSocketClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
var
UserSession: pTUserSession;
sRemoteIPaddr, sLocalIPaddr: string;
nSockIndex: Integer;
begin
Socket.nIndex := -1;
sRemoteIPaddr := Socket.RemoteAddress;
if g_boDynamicIPDisMode then begin
sLocalIPaddr := ClientSocket.Socket.RemoteAddress;
end else begin
sLocalIPaddr := Socket.LocalAddress;
end;
if IsBlockIP(sRemoteIPaddr) then begin
MainOutMessage('过滤连接: ' + sRemoteIPaddr, 1);
Socket.Close;
Exit;
end;
if IsConnLimited(sRemoteIPaddr) then begin
case BlockMethod of
mDisconnect: begin
Socket.Close;
end;
mBlock: begin
AddTempBlockIP(sRemoteIPaddr);
CloseConnect(sRemoteIPaddr);
end;
mBlockList: begin
AddBlockIP(sRemoteIPaddr);
CloseConnect(sRemoteIPaddr);
end;
end;
MainOutMessage('端口攻击: ' + sRemoteIPaddr, 1);
Exit;
end;
if boGateReady then begin
for nSockIndex := 0 to GATEMAXSESSION - 1 do begin
UserSession := @g_SessionArray[nSockIndex];
if UserSession.Socket = nil then begin
UserSession.Socket := Socket;
UserSession.sRemoteIPaddr := sRemoteIPaddr;
UserSession.nSendMsgLen := 0;
UserSession.nReceiveMsgLen := 0;
UserSession.bo0C := False;
UserSession.dw10Tick := GetTickCount();
UserSession.dwConnctCheckTick := GetTickCount();
UserSession.boSendAvailable := True;
UserSession.boSendCheck := False;
UserSession.nCheckSendLength := 0;
UserSession.n20 := 0;
UserSession.dwUserTimeOutTick := GetTickCount();
UserSession.SocketHandle := Socket.SocketHandle;
UserSession.sIP := sRemoteIPaddr;
UserSession.dwReceiveTick := GetTickCount();
UserSession.MsgList.Clear;
Socket.nIndex := nSockIndex;
Inc(nSessionCount);
break;
end;
end;
if Socket.nIndex >= 0 then begin
ClientSocket.Socket.SendText('%N' +
IntToStr(Socket.SocketHandle) +
'/' +
sRemoteIPaddr +
'/' +
sLocalIPaddr +
'$');
MainOutMessage('Connect: ' + sRemoteIPaddr, 5);
end else begin
Socket.Close;
MainOutMessage('Kick Off: ' + sRemoteIPaddr, 1);
end;
end else begin //0x004529EF
Socket.Close;
MainOutMessage('Kick Off: ' + sRemoteIPaddr, 1);
end;
end;
procedure TFrmMain.ServerSocketClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
I: Integer;
UserSession: pTUserSession;
nSockIndex: Integer;
sRemoteIPaddr: string;
nIPaddr: Integer;
IPList: TList;
begin
sRemoteIPaddr := Socket.RemoteAddress;
nSockIndex := Socket.nIndex;
nIPaddr := inet_addr(PChar(sRemoteIPaddr));
CurrIPaddrList.Lock;
try
for I := CurrIPaddrList.Count - 1 downto 0 do begin
IPList := TList(CurrIPaddrList.Items[I]);
if IPList <> nil then begin
if pTSockaddr(IPList.Items[0]) <> nil then begin
if pTSockaddr(IPList.Items[0]).nIPaddr = nIPaddr then begin
Dispose(pTSockaddr(IPList.Items[0]));
IPList.Delete(0);
if IPList.Count <= 0 then begin
IPList.Free;
CurrIPaddrList.Delete(I);
end;
break;
end;
end;
end;
end;
finally
CurrIPaddrList.UnLock;
end;
if (nSockIndex >= 0) and (nSockIndex < GATEMAXSESSION) then begin
UserSession := @g_SessionArray[nSockIndex];
UserSession.Socket := nil;
UserSession.sRemoteIPaddr := '';
UserSession.SocketHandle := -1;
UserSession.MsgList.Clear;
Dec(nSessionCount);
if boGateReady then begin
ClientSocket.Socket.SendText('%C' +
IntToStr(Socket.SocketHandle) +
'$');
MainOutMessage('DisConnect: ' + sRemoteIPaddr, 5);
end;
end;
end;
procedure TFrmMain.ServerSocketClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
StringList30C.Add('Error ' + IntToStr(ErrorCode) + ': ' + Socket.RemoteAddress);
Socket.Close;
ErrorCode := 0;
end;
procedure TFrmMain.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
UserSession: pTUserSession;
nSockIndex: Integer;
sRemoteAddress, sReviceMsg, s10, s1C: string;
nPos: Integer;
nMsgLen: Integer;
nIPaddr: Integer;
nMsgCount: Integer;
bo01: Boolean;
bo02: Boolean;
begin
bo01 := False;
bo02 := False;
nSockIndex := Socket.nIndex;
sRemoteAddress := Socket.RemoteAddress;
if (nSockIndex >= 0) and (nSockIndex < GATEMAXSESSION) then begin
UserSession := @g_SessionArray[nSockIndex];
sReviceMsg := Socket.ReceiveText;
if (sReviceMsg <> '') and (boServerReady) then begin
nPos := Pos('*', sReviceMsg);
if nPos > 0 then begin
UserSession.boSendAvailable := True;
UserSession.boSendCheck := False;
UserSession.nCheckSendLength := 0;
UserSession.dwReceiveTick := GetTickCount();
s10 := Copy(sReviceMsg, 1, nPos - 1);
s1C := Copy(sReviceMsg, nPos + 1, Length(sReviceMsg) - nPos);
sReviceMsg := s10 + s1C;
end;
nMsgLen := Length(sReviceMsg);
if nAttackLevel > 0 then begin
Inc(UserSession.nReceiveMsgLen, nMsgLen);
nMsgCount := TagCount(sReviceMsg, '!');
if nMsgCount > nMaxClientMsgCount * nAttackLevel then bo02 := True;
if (GetTickCount - UserSession.dwReceiveTick) >= dwReviceTick * nAttackLevel then begin //100
UserSession.dwReceiveTick := GetTickCount;
if UserSession.nReceiveMsgLen > nReviceMsgLength * nAttackLevel then begin //100
bo01 := True;
end else begin
UserSession.nReceiveMsgLen := 0;
end;
end;
if bo01 or bo02 then begin
case BlockMethod of
mDisconnect: begin
//Socket.Close;
end;
mBlock: begin
AddTempBlockIP(sRemoteAddress);
CloseConnect(sRemoteAddress);
end;
mBlockList: begin
AddBlockIP(sRemoteAddress);
CloseConnect(sRemoteAddress);
end;
end;
if bo01 then
MainOutMessage('端口攻击: ' + sRemoteAddress + ' 数据包长度: ' + IntToStr(UserSession.nReceiveMsgLen), 1);
if bo02 then
MainOutMessage('端口攻击: ' + sRemoteAddress + '信息数量:' + IntToStr(nMsgCount), 1);
Socket.Close;
Exit;
end;
end;
if (sReviceMsg <> '') and (boGateReady) and (not boKeepAliveTimcOut) then begin
UserSession.dwConnctCheckTick := GetTickCount();
if (GetTickCount - UserSession.dwUserTimeOutTick) < 1000 then begin
Inc(UserSession.n20, nMsgLen);
end else UserSession.n20 := nMsgLen;
ClientSocket.Socket.SendText('%D' +
IntToStr(Socket.SocketHandle) +
'/' +
sReviceMsg +
'$');
end;
end;
end;
end;
procedure TFrmMain.MemoLogChange(Sender: TObject);
begin
if MemoLog.Lines.Count > 200 then MemoLog.Clear;
end;
procedure TFrmMain.FormDestroy(Sender: TObject);
var
nIndex: Integer;
begin
StringList30C.Free;
TempLogList.Free;
for nIndex := 0 to GATEMAXSESSION - 1 do begin
g_SessionArray[nIndex].MsgList.Free;
end;
end;
procedure TFrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if boClose then Exit;
if Application.MessageBox('是否确认退出服务器?',
'提示信息',
MB_YESNO + MB_ICONQUESTION) = IDYES then begin
if boServiceStart then begin
StartTimer.Enabled := True;
CanClose := False;
end;
end else CanClose := False;
end;
procedure TFrmMain.ClientSocketConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
boGateReady := True;
nSessionCount := 0;
dwKeepAliveTick := GetTickCount();
ResUserSessionArray();
boServerReady := True;
end;
procedure TFrmMain.ClientSocketDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var
UserSession: pTUserSession;
nIndex: Integer;
begin
for nIndex := 0 to GATEMAXSESSION - 1 do begin
UserSession := @g_SessionArray[nIndex];
if UserSession.Socket <> nil then
UserSession.Socket.Close;
UserSession.Socket := nil;
UserSession.sRemoteIPaddr := '';
UserSession.SocketHandle := -1;
end;
ResUserSessionArray();
ClientSockeMsgList.Clear;
boGateReady := False;
nSessionCount := 0;
end;
procedure TFrmMain.ClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
Socket.Close;
ErrorCode := 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -