本文目录导读:

我来分享一个Python实现IP拦截的完整案例,包含多种实现方式:
基于访问频率的IP拦截(Flask示例)
from flask import Flask, request, abort
from collections import defaultdict
import time
from datetime import datetime
import redis
import ipaddress
app = Flask(__name__)
class IPBlocker:
def __init__(self):
# 本地内存存储(单机使用)
self.ip_access = defaultdict(list)
# 白名单
self.whitelist = ['192.168.1.1', '10.0.0.1']
# 黑名单
self.blacklist = set()
# 配置
self.max_requests = 100 # 最大请求数
self.time_window = 60 # 时间窗口(秒)
self.block_time = 3600 # 封禁时间(秒)
def is_banned(self, ip):
"""检查IP是否被封禁"""
if ip in self.blacklist:
return True
return False
def check_rate_limit(self, ip):
"""检查访问频率"""
now = time.time()
# 清除过期记录
self.ip_access[ip] = [
t for t in self.ip_access[ip]
if now - t < self.time_window
]
# 添加当前请求时间
self.ip_access[ip].append(now)
# 判断是否超过限制
if len(self.ip_access[ip]) > self.max_requests:
self.blacklist.add(ip)
return False
return True
def validate_ip(self, ip):
"""验证IP地址合法性"""
try:
ipaddress.ip_address(ip)
return True
except ValueError:
return False
# 初始化IP拦截器
ip_blocker = IPBlocker()
@app.before_request
def block_malicious_ips():
"""请求前拦截恶意IP"""
ip = request.remote_addr
# 检查白名单
if ip in ip_blocker.whitelist:
return None
# 检查黑名单
if ip_blocker.is_banned(ip):
abort(403, description="IP已被封禁")
# 检查访问频率
if not ip_blocker.check_rate_limit(ip):
abort(429, description="请求过于频繁")
return None
@app.route('/')
def index():
return "正常访问"
if __name__ == '__main__':
app.run(debug=True)
基于Redis的分布式IP拦截
import redis
import time
from functools import wraps
from flask import Flask, request, abort
app = Flask(__name__)
class RedisIPBlocker:
def __init__(self, redis_host='localhost', redis_port=6379):
self.redis_client = redis.Redis(
host=redis_host,
port=redis_port,
decode_responses=True
)
self.block_prefix = "blocked_ip:"
self.count_prefix = "ip_count:"
self.max_requests = 100
self.time_window = 60
self.block_time = 3600
def is_blocked(self, ip):
"""检查IP是否被封锁"""
return self.redis_client.exists(f"{self.block_prefix}{ip}")
def increment_count(self, ip):
"""增加访问计数"""
key = f"{self.count_prefix}{ip}"
count = self.redis_client.incr(key)
# 设置过期时间
if count == 1:
self.redis_client.expire(key, self.time_window)
return count
def block_ip(self, ip):
"""封禁IP"""
self.redis_client.setex(
f"{self.block_prefix}{ip}",
self.block_time,
"blocked"
)
# 清除计数
self.redis_client.delete(f"{self.count_prefix}{ip}")
def check_ip(self, ip):
"""检查IP是否需要拦截"""
# 检查是否已被封禁
if self.is_blocked(ip):
return False
# 增加计数并检查是否超限
count = self.increment_count(ip)
if count > self.max_requests:
self.block_ip(ip)
return False
return True
# 初始化
redis_blocker = RedisIPBlocker()
@app.before_request
def rate_limit():
ip = request.remote_addr
# 白名单检查(可放在Redis中)
whitelist = redis_blocker.redis_client.smembers("whitelist")
if ip in whitelist:
return None
if not redis_blocker.check_ip(ip):
abort(403, description="IP已被限制访问")
@app.route('/')
def index():
return "访问成功"
if __name__ == '__main__':
app.run()
基于IP段的批量拦截
import ipaddress
from flask import Flask, request, abort
app = Flask(__name__)
class IPRangeBlocker:
def __init__(self):
# 配置需要拦截的IP段(来自威胁情报)
self.blocked_ranges = [
ipaddress.ip_network('192.168.0.0/16'),
ipaddress.ip_network('10.0.0.0/8'),
ipaddress.ip_network('172.16.0.0/12'),
]
# 恶意IP名单
self.malicious_ips = set()
# 从文件加载恶意IP
self.load_malicious_ips()
def load_malicious_ips(self):
"""从文件加载恶意IP列表"""
try:
with open('malicious_ips.txt', 'r') as f:
for line in f:
ip = line.strip()
if ip:
self.malicious_ips.add(ip)
except FileNotFoundError:
print("恶意IP文件未找到,使用默认配置")
def is_blocked_ip(self, ip):
"""检查IP是否在拦截范围内"""
try:
ip_obj = ipaddress.ip_address(ip)
# 检查是否在拦截的IP段内
for network in self.blocked_ranges:
if ip_obj in network:
return True
# 检查是否在恶意IP列表中
if ip in self.malicious_ips:
return True
return False
except ValueError:
return True # 非法IP直接拦截
# 初始化
ip_range_blocker = IPRangeBlocker()
@app.before_request
def check_ip_range():
ip = request.remote_addr
if ip_range_blocker.is_blocked_ip(ip):
abort(403, description="IP不在允许访问范围内")
@app.route('/')
def index():
return "访问成功"
if __name__ == '__main__':
app.run()
完整的防火墙脚本
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import subprocess
import re
import sys
import time
from collections import defaultdict
import logging
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('ip_blocker.log'),
logging.StreamHandler()
]
)
class IPFirewall:
def __init__(self):
self.iptables_cmd = '/sbin/iptables'
self.ipset_cmd = '/usr/sbin/ipset'
self.blacklist_file = '/etc/ip_blacklist.txt'
self.whitelist_file = '/etc/ip_whitelist.txt'
# 配置规则
self.max_connections = 50
self.check_interval = 10 # 检查间隔(秒)
def check_root(self):
"""检查是否为root用户"""
if os.geteuid() != 0:
logging.error("需要root权限运行此脚本")
sys.exit(1)
def add_iptables_rule(self, ip):
"""添加iptables规则"""
try:
subprocess.run([
self.iptables_cmd, '-A', 'INPUT',
'-s', ip,
'-j', 'DROP'
], check=True, capture_output=True)
logging.info(f"已添加iptables规则:禁止 {ip}")
except subprocess.CalledProcessError as e:
logging.error(f"添加iptables规则失败:{e}")
def remove_iptables_rule(self, ip):
"""移除iptables规则"""
try:
subprocess.run([
self.iptables_cmd, '-D', 'INPUT',
'-s', ip,
'-j', 'DROP'
], check=True, capture_output=True)
logging.info(f"已移除iptables规则:允许 {ip}")
except subprocess.CalledProcessError as e:
logging.error(f"移除iptables规则失败:{e}")
def add_to_ipset(self, ip):
"""添加到ipset"""
try:
subprocess.run([
self.ipset_cmd, 'add', 'blacklist', ip
], check=True, capture_output=True)
logging.info(f"已将 {ip} 添加到ipset黑名单")
except subprocess.CalledProcessError as e:
logging.error(f"添加ipset失败:{e}")
def block_ip_permanently(self, ip):
"""永久封禁IP"""
# 添加到iptables
self.add_iptables_rule(ip)
# 写入黑名单文件
with open(self.blacklist_file, 'a') as f:
f.write(f"{ip}\n")
logging.info(f"已永久封禁IP: {ip}")
def unblock_ip(self, ip):
"""解封IP"""
self.remove_iptables_rule(ip)
logging.info(f"已解封IP: {ip}")
def load_blacklist(self):
"""加载黑名单"""
try:
with open(self.blacklist_file, 'r') as f:
for line in f:
ip = line.strip()
if ip and not ip.startswith('#'):
self.add_iptables_rule(ip)
except FileNotFoundError:
logging.warning("黑名单文件不存在")
def analyze_logs(self, log_file='/var/log/auth.log'):
"""分析系统日志识别恶意IP"""
ip_attempts = defaultdict(int)
try:
with open(log_file, 'r') as f:
for line in f:
# 匹配失败登录尝试
if 'Failed password' in line:
match = re.search(r'from (\d+\.\d+\.\d+\.\d+)', line)
if match:
ip = match.group(1)
ip_attempts[ip] += 1
except FileNotFoundError:
logging.error(f"日志文件 {log_file} 不存在")
return ip_attempts
return ip_attempts
def check_and_block(self):
"""检查并封禁恶意IP"""
ip_attempts = self.analyze_logs()
for ip, attempts in ip_attempts.items():
if attempts >= self.max_connections:
self.block_ip_permanently(ip)
logging.warning(f"检测到暴力破解攻击:{ip} (尝试次数:{attempts})")
def start_monitoring(self):
"""开始监控"""
logging.info("IP防火墙监控已启动")
while True:
try:
self.check_and_block()
time.sleep(self.check_interval)
except KeyboardInterrupt:
logging.info("监控已停止")
break
except Exception as e:
logging.error(f"监控出错:{e}")
time.sleep(self.check_interval)
if __name__ == '__main__':
import os
firewall = IPFirewall()
firewall.check_root()
firewall.start_monitoring()
配置文件和用法
配置文件 config.py
# IP拦截配置
IP_BLOCK_CONFIG = {
'redis': {
'host': 'localhost',
'port': 6379,
'db': 0
},
'rate_limit': {
'max_requests': 100,
'time_window': 60, # 60秒内
'block_time': 3600 # 封禁1小时
},
'whitelist': [
'127.0.0.1',
'192.168.1.0/24',
'10.0.0.0/8'
],
'blacklist_file': '/etc/ip_blacklist.txt',
'log_file': '/var/log/nginx/access.log',
'monitor_interval': 10 # 监控间隔(秒)
}
Docker部署示例
FROM python:3.9-alpine WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . # 添加iptables支持 RUN apk add --no-cache iptables ipset EXPOSE 5000 CMD ["python", "app.py"]
最佳实践建议
- 多层防御:结合多种拦截方法(频率、IP段、行为分析)
- 日志记录:记录所有拦截行为方便分析
- 定期更新:保持恶意IP库更新
- 性能优化:使用Redis、ipset等提高性能
- 误报处理:提供白名单机制
- 监控告警:集成告警系统
这些代码可以根据实际需求进行配置和扩展,建议先在测试环境运行,确认无误后再部署到生产环境。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播