在TidHTTPServer中阻止传入IP:OnConnect拦截客户端的事件与IP获取疑问
在TIdHTTPServer中拦截特定客户端IP(OnConnect阶段)
刚好我之前处理过类似的需求,咱们一步步来解决你的问题:
一、选对拦截事件:OnConnecting vs OnConnect
如果你想在连接真正建立前就拦截(更高效,节省服务器资源),优先用OnConnecting事件;如果是连接建立后立即检查并断开,用OnConnect事件也可以。前者是在客户端发起连接请求时触发,还没完成TCP握手;后者是握手完成后触发。
二、获取客户端远程IP地址
不管用哪个事件,都可以通过TIdContext参数的Binding.PeerIP属性直接拿到客户端的IP地址。这个属性会返回字符串格式的IP(比如192.168.1.100),不需要额外解析。
三、实现拦截逻辑的代码示例
用OnConnecting事件(推荐)
这个事件里断开连接,客户端会直接收到连接被拒绝的反馈,服务器也不会为这个连接分配多余资源:
procedure TYourForm.IdHTTPServer1Connecting(AContext: TIdContext); var ClientIP: string; BlockedIPs: TStringList; begin // 获取客户端IP ClientIP := AContext.Binding.PeerIP; // 模拟黑名单(实际建议从配置文件读取) BlockedIPs := TStringList.Create; try BlockedIPs.Add('192.168.1.100'); BlockedIPs.Add('10.0.0.5'); BlockedIPs.Add('203.0.113.45'); // 检查是否在黑名单中 if BlockedIPs.IndexOf(ClientIP) <> -1 then begin // 拒绝连接 AContext.Connection.Disconnect; // 记录日志(可选) LogMessage(Format('Blocked connection from IP: %s at %s', [ClientIP, TimeToStr(Now)])); end; finally BlockedIPs.Free; end; end;
用OnConnect事件(连接建立后断开)
如果因为某些原因你需要在连接建立后处理,逻辑类似:
procedure TYourForm.IdHTTPServer1Connect(AContext: TIdContext); var ClientIP: string; begin ClientIP := AContext.Binding.PeerIP; // 检查黑名单(这里简化判断,实际建议用高效的查找方式) if (ClientIP = '192.168.1.100') or (ClientIP.StartsWith('10.0.0.')) then begin // 断开已建立的连接 AContext.Connection.Disconnect; LogMessage(Format('Disconnected blocked IP: %s at %s', [ClientIP, TimeToStr(Now)])); end; end;
四、优化建议
- 黑名单管理:别硬编码IP,把黑名单存在配置文件(比如INI、JSON)里,支持动态加载,不用重启服务器就能更新。
- 高效查找:如果黑名单IP数量多,用
TStringList.IndexOf效率低,建议改用TDictionary<string, Boolean>或者THashedStringList,查找速度会快很多。 - 日志完善:除了IP和时间,还可以记录客户端的端口(
AContext.Binding.PeerPort),方便更精准排查。
内容的提问来源于stack exchange,提问作者Wolfgang Bures
相关产品推荐
相关产品推荐

