🛡️【开源工具】Windows一键配置防火墙阻止策略(禁止应用联网)| 附完整源码
![图片[1] - 【开源工具】Windows一键配置防火墙阻止策略(禁止应用联网)| 附完整Python源码 - 宋马](https://pic.songma.com/blogimg/20250707/22c303f0b5964acaafd64b698526a5c5.gif)

🌈 个人主页:创客白泽 – CSDN博客
🔥 系列专栏:🐍《Python开源项目实战》
💡 热爱不止于代码,热情源自每一个灵感闪现的夜晚。愿以开源之火,点亮前行之路。
🐋 希望大家多多支持,我们一起进步!
👍 🎉如果文章对你有帮助的话,欢迎 点赞 👍🏻 评论 💬 收藏 ⭐️ 加已关注+💗分享给更多人哦


📜 文章目录
项目概述
功能特性
效果展示
实现原理
代码深度解析
项目结构图
使用指南
源码下载
总结与拓展
🌟 项目概述
在Windows系统管理中,防火墙规则配置是保障系统安全的重要手段。CSDN论坛里也有不少禁止软件自动联网、检查更新的教程,方法都是配置防火墙的出站/入站阻止规则。但如果安装目录下面文件很多很杂,手动查找他们然后一个个复制路径、配置规则很繁琐。传统通过netsh命令行或图形界面操作防火墙规则的方式效率低下,特别是需要批量管理多个应用程序的网络权限时。本项目基于PyQt5开发了一个可视化工具,可以自动查找所在目录(及子目录)下所有的.exe可执行文件,一次性配置所有的出入站阻止规则。经测试有效。实现了以下核心价值:
可视化操作:将复杂的命令行操作转化为直观的GUI界面
批量处理:支持目录扫描和拖拽添加,可同时处理多个EXE文件
权限管理:自动检测并提示管理员权限需求
操作审计:清晰的进度反馈和状态提示
注意: 如果电脑正在开启某种软件的系统代{过}{滤}理,防火墙阻止策略会暂时失效,手动配置的结果也是一样的
🔍 技术栈:PyQt5 + Windows API + netsh命令 + 多线程处理
🎯 功能特性
1. 文件管理功能
支持拖放添加EXE文件(符合Windows UX规范)
目录递归扫描(自动过滤非EXE文件)
列表多选操作(Shift/Ctrl组合键支持)
2. 防火墙操作
| 功能 | 入站规则 | 出站规则 | 实现方式 |
|---|---|---|---|
| 阻止通信 | ✅ | ✅ | netsh advfirewall add rule |
| 恢复通信 | ✅ | ✅ | netsh advfirewall delete rule |
| 批量操作 | ✅ | ✅ | 多线程队列处理 |
3. 特色功能
🚨 自动管理员权限检测与提权
📊 实时进度显示(进度条+文字反馈)
🔗 快速跳转防火墙高级设置
🎨 现代化UI设计(支持主题定制)
🖼 效果展示
1. 主界面截图

2. 操作演示截图

2. 效果演示截图
![图片[2] - 【开源工具】Windows一键配置防火墙阻止策略(禁止应用联网)| 附完整Python源码 - 宋马](https://pic.songma.com/blogimg/20250707/7b271d1a967c4f058fd55cea39682ebb.png)

🔧 实现原理
系统架构图
关键技术点
netsh命令封装
# 阻止入站示例
netsh advfirewall firewall add rule
name="Block In: app.exe"
dir=in
program="C:app.exe"
action=block
UAC提权机制
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, " ".join(sys.argv), None, 1
)
PyQt5多线程通信
class FirewallWorker(QThread):
progress = pyqtSignal(int) # 进度信号
message = pyqtSignal(str) # 消息信号
🧩 代码深度解析
1. 拖放功能实现
核心代码在FileListWidget类中重写拖放事件:
def dropEvent(self, event: QDropEvent):
for url in event.mimeData().urls():
file_path = Path(url.toLocalFile())
if file_path.suffix.lower() == '.exe':
self.parent().add_exe_file(file_path)
2. 防火墙规则生成器
采用Builder模式构造netsh命令:
def generate_rule(exe_path, operation):
rules = {
'block_in': f'netsh advfirewall firewall add rule name="... dir=in ...',
'block_out': f'netsh advfirewall firewall add rule name="... dir=out ...'
}
return rules.get(operation, '')
3. 线程安全处理
使用信号槽机制更新UI:
self.worker.progress.connect(self.update_progress)
self.worker.message.connect(self.update_status)
📂 项目结构图
Firewall-Tool/
├── main.py # 程序入口
├── ui/
│ ├── main_window.py # 主窗口实现
│ └── components/ # 自定义组件
├── core/
│ ├── firewall.py # 防火墙操作核心
│ └── worker.py # 线程工作器
└── resources/ # 静态资源
🛠 使用指南
1. 环境准备
pip install pyqt5 ctypes
2. 操作流程
通过”选择文件/目录”或拖拽方式添加EXE
选择需要阻止/恢复的通信方向
确认操作等待执行完成
可通过系统防火墙设置验证规则
3. 注意事项
必须使用管理员权限运行
杀毒软件可能拦截netsh操作
规则名称包含emoji可能显示异常
⬇️ 源码下载
import os
import sys
import ctypes
import subprocess
from pathlib import Path
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QPushButton, QListWidget, QMessageBox, QProgressBar,
QCheckBox, QGroupBox, QFileDialog, QAbstractItemView)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QMimeData, QUrl
from PyQt5.QtGui import QFont, QIcon
from PyQt5.QtCore import QEvent, QObject
from PyQt5.QtGui import QDragEnterEvent, QDragMoveEvent, QDropEvent
class FirewallWorker(QThread):
progress = pyqtSignal(int)
message = pyqtSignal(str)
finished = pyqtSignal()
def __init__(self, exe_files, operation_type):
super().__init__()
self.exe_files = exe_files
self.operation_type = operation_type # 'block_in', 'block_out', 'unblock_in', 'unblock_out'
self._is_running = True
def run(self):
total = len(self.exe_files)
for i, exe_file in enumerate(self.exe_files):
if not self._is_running:
break
exe_path = str(exe_file.resolve())
self.message.emit(f"处理中: {
exe_path}")
try:
if self.operation_type == 'block_in':
command = (
f'netsh advfirewall firewall add rule '
f'name="🚫 Block In: {
exe_path}" '
f'dir=in program="{
exe_path}" action=block'
)
elif self.operation_type == 'block_out':
command = (
f'netsh advfirewall firewall add rule '
f'name="🚫 Block Out: {
exe_path}" '
f'dir=out program="{
exe_path}" action=block'
)
elif self.operation_type == 'unblock_in':
command = (
f'netsh advfirewall firewall delete rule '
f'name="🚫 Block In: {
exe_path}" dir=in'
)
elif self.operation_type == 'unblock_out':
command = (
f'netsh advfirewall firewall delete rule '
f'name="🚫 Block Out: {
exe_path}" dir=out'
)
subprocess.run(command, shell=True, check=False)
self.progress.emit(int((i + 1) / total * 100))
except Exception as e:
self.message.emit(f"❌ 错误: {
str(e)}")
self.finished.emit()
def stop(self):
self._is_running = False
class FileListWidget(QListWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAcceptDrops(True)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
def dragEnterEvent(self, event: QDragEnterEvent):
if event.mimeData().hasUrls():
event.acceptProposedAction()
def dragMoveEvent(self, event: QDragMoveEvent):
event.accept()
def dropEvent(self, event: QDropEvent):
parent = self.parent()
while parent and not hasattr(parent, 'add_exe_file'):
parent = parent.parent()
if parent:
for url in event.mimeData().urls():
file_path = Path(url.toLocalFile())
if file_path.suffix.lower() == '.exe':
parent.add_exe_file(file_path)
elif file_path.is_dir():
parent.add_exe_files_from_dir(str(file_path))
class FirewallApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("防火墙禁止应用联网工具")
self.setGeometry(100, 100, 800, 600)
self.setWindowIcon(QIcon(self.get_icon_path()))
self.exe_files = []
self.worker = None
self.init_ui()
self.check_admin()
def get_icon_path(self):
paths = [
"C:/Windows/System32/imageres.dll",
"C:/Windows/System32/shell32.dll"
]
for path in paths:
if os.path.exists(path):
return path
return None
def init_ui(self):
main_widget = QWidget()
main_layout = QVBoxLayout()
# Header
header = QLabel("🛡 防火墙禁止应用联网工具")
header.setFont(QFont("Arial", 18, QFont.Bold))
header.setAlignment(Qt.AlignCenter)
header.setStyleSheet("color: #2c3e50; margin-bottom: 20px;")
# File selection
file_group = QGroupBox("📁 文件选择 (拖放EXE文件到下方区域)")
file_layout = QVBoxLayout()
# Selection buttons
btn_layout = QHBoxLayout()
dir_btn = QPushButton("选择目录...")
dir_btn.setStyleSheet(self.get_button_style("#3498db", "#2980b9"))
dir_btn.clicked.connect(self.browse_directory)
file_btn = QPushButton("选择文件...")
file_btn.setStyleSheet(self.get_button_style("#3498db", "#2980b9"))
file_btn.clicked.connect(self.browse_file)
clear_btn = QPushButton("清空列表")
clear_btn.setStyleSheet(self.get_button_style("#e74c3c", "#c0392b"))
clear_btn.clicked.connect(self.clear_list)
btn_layout.addWidget(dir_btn)
btn_layout.addWidget(file_btn)
btn_layout.addWidget(clear_btn)
# File list with drag-drop support
self.file_list = FileListWidget()
self.file_list.setStyleSheet("""
QListWidget {
border: 1px solid #bdc3c7;
border-radius: 4px;
padding: 5px;
min-height: 200px;
}
""")
file_layout.addLayout(btn_layout)
file_layout.addWidget(self.file_list)
file_group.setLayout(file_layout)
# Firewall operations
ops_group = QGroupBox("⚙️ 防火墙操作")
ops_layout = QVBoxLayout()
# Block operations
block_group = QGroupBox("🚫 阻止通信")
block_layout = QHBoxLayout()
block_in_btn = QPushButton("阻止入站")
block_in_btn.setStyleSheet(self.get_button_style("#e74c3c", "#c0392b"))
block_in_btn.clicked.connect(lambda: self.block_selected('in'))
block_out_btn = QPushButton("阻止出站")
block_out_btn.setStyleSheet(self.get_button_style("#e74c3c", "#c0392b"))
block_out_btn.clicked.connect(lambda: self.block_selected('out'))
block_both_btn = QPushButton("阻止全部")
block_both_btn.setStyleSheet(self.get_button_style("#e74c3c", "#c0392b"))
block_both_btn.clicked.connect(lambda: self.block_selected('both'))
block_layout.addWidget(block_in_btn)
block_layout.addWidget(block_out_btn)
block_layout.addWidget(block_both_btn)
block_group.setLayout(block_layout)
# Unblock operations
unblock_group = QGroupBox("✅ 恢复通信")
unblock_layout = QHBoxLayout()
unblock_in_btn = QPushButton("恢复入站")
unblock_in_btn.setStyleSheet(self.get_button_style("#2ecc71", "#27ae60"))
unblock_in_btn.clicked.connect(lambda: self.unblock_selected('in'))
unblock_out_btn = QPushButton("恢复出站")
unblock_out_btn.setStyleSheet(self.get_button_style("#2ecc71", "#27ae60"))
unblock_out_btn.clicked.connect(lambda: self.unblock_selected('out'))
unblock_both_btn = QPushButton("恢复全部")
unblock_both_btn.setStyleSheet(self.get_button_style("#2ecc71", "#27ae60"))
unblock_both_btn.clicked.connect(lambda: self.unblock_selected('both'))
unblock_layout.addWidget(unblock_in_btn)
unblock_layout.addWidget(unblock_out_btn)
unblock_layout.addWidget(unblock_both_btn)
unblock_group.setLayout(unblock_layout)
ops_layout.addWidget(block_group)
ops_layout.addWidget(unblock_group)
ops_group.setLayout(ops_layout)
# Progress and status
self.progress_bar = QProgressBar()
self.progress_bar.setStyleSheet("""
QProgressBar {
border: 1px solid #bdc3c7;
border-radius: 4px;
text-align: center;
}
QProgressBar::chunk {
background-color: #3498db;
width: 10px;
}
""")
self.progress_bar.setVisible(False)
self.status_label = QLabel("就绪")
self.status_label.setStyleSheet("color: #7f8c8d; font-style: italic;")
# Firewall settings button
firewall_btn = QPushButton("🔥 打开防火墙高级设置")
firewall_btn.setStyleSheet(self.get_button_style("#9b59b6", "#8e44ad"))
firewall_btn.clicked.connect(self.open_firewall_settings)
# Assemble main layout
main_layout.addWidget(header)
main_layout.addWidget(file_group)
main_layout.addWidget(ops_group)
main_layout.addWidget(self.progress_bar)
main_layout.addWidget(self.status_label)
main_layout.addWidget(firewall_btn)
main_widget.setLayout(main_layout)
self.setCentralWidget(main_widget)
self.apply_light_theme()
def get_button_style(self, normal_color, hover_color):
return f"""
QPushButton {
{
background-color: {
normal_color};
color: white;
border: none;
padding: 8px 15px;
border-radius: 4px;
font-weight: bold;
min-width: 80px;
}}
QPushButton:hover {
{
background-color: {
hover_color};
}}
QPushButton:disabled {
{
background-color: #95a5a6;
}}
"""
def apply_light_theme(self):
self.setStyleSheet("""
QMainWindow {
background-color: #ecf0f1;
}
QGroupBox {
border: 1px solid #bdc3c7;
border-radius: 5px;
margin-top: 10px;
padding-top: 15px;
font-weight: bold;
color: #2c3e50;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 10px;
padding: 0 3px;
}
""")
def check_admin(self):
if not ctypes.windll.shell32.IsUserAnAdmin():
QMessageBox.warning(
self,
"⚠️ 需要管理员权限",
"此程序需要管理员权限才能修改防火墙设置。
请以管理员身份重新运行。",
QMessageBox.Ok
)
self.relaunch_as_admin()
def relaunch_as_admin(self):
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, " ".join(sys.argv), None, 1
)
sys.exit()
def browse_directory(self):
dir_path = QFileDialog.getExistingDirectory(
self,
"选择目录",
os.getcwd(),
QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks
)
if dir_path:
self.add_exe_files_from_dir(dir_path)
def browse_file(self):
file_path, _ = QFileDialog.getOpenFileName(
self,
"选择EXE文件",
os.getcwd(),
"Executable Files (*.exe)"
)
if file_path:
self.add_exe_file(Path(file_path))
def add_exe_files_from_dir(self, dir_path):
current_path = Path(dir_path)
exe_files = []
for root, _, files in os.walk(current_path):
for file in files:
if file.lower().endswith('.exe'):
exe_path = Path(root) / file
if exe_path != Path(sys.executable):
exe_files.append(exe_path)
for exe_file in exe_files:
self.add_exe_file(exe_file)
if not exe_files:
self.status_label.setText("⚠️ 目录下未找到任何exe文件")
else:
self.status_label.setText(f"添加了 {
len(exe_files)} 个可执行文件")
def add_exe_file(self, exe_path):
if exe_path.suffix.lower() != '.exe':
return
if exe_path == Path(sys.executable):
return
if exe_path not in self.exe_files:
self.exe_files.append(exe_path)
self.file_list.addItem(str(exe_path))
self.status_label.setText(f"已添加: {
exe_path.name}")
def clear_list(self):
self.exe_files = []
self.file_list.clear()
self.status_label.setText("已清空文件列表")
def get_selected_files(self):
selected_files = []
for item in self.file_list.selectedItems():
file_path = Path(item.text())
if file_path in self.exe_files:
selected_files.append(file_path)
return selected_files if selected_files else self.exe_files
def block_selected(self, direction):
files = self.get_selected_files()
if not files:
QMessageBox.warning(self, "警告", "没有选择任何文件!", QMessageBox.Ok)
return
confirm_msg = {
'in': f"确定要阻止 {
len(files)} 个程序的入站通信吗?",
'out': f"确定要阻止 {
len(files)} 个程序的出站通信吗?",
'both': f"确定要阻止 {
len(files)} 个程序的所有通信吗?"
}[direction]
reply = QMessageBox.question(
self, "确认", confirm_msg, QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.No:
return
operations = {
'in': ['block_in'],
'out': ['block_out'],
'both': ['block_in', 'block_out']
}[direction]
self.start_operations(files, operations)
def unblock_selected(self, direction):
files = self.get_selected_files()
if not files:
QMessageBox.warning(self, "警告", "没有选择任何文件!", QMessageBox.Ok)
return
confirm_msg = {
'in': f"确定要恢复 {
len(files)} 个程序的入站通信吗?",
'out': f"确定要恢复 {
len(files)} 个程序的出站通信吗?",
'both': f"确定要恢复 {
len(files)} 个程序的所有通信吗?"
}[direction]
reply = QMessageBox.question(
self, "确认", confirm_msg, QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.No:
return
operations = {
'in': ['unblock_in'],
'out': ['unblock_out'],
'both': ['unblock_in', 'unblock_out']
}[direction]
self.start_operations(files, operations)
def start_operations(self, files, operations):
self.progress_bar.setVisible(True)
self.progress_bar.setValue(0)
self.status_label.setText("正在处理...")
# Chain operations
self.current_operation_index = 0
self.operations = operations
self.files_to_process = files
self.start_next_operation()
def start_next_operation(self):
if self.current_operation_index >= len(self.operations):
self.on_operations_finished()
return
op_type = self.operations[self.current_operation_index]
op_name = {
'block_in': "阻止入站",
'block_out': "阻止出站",
'unblock_in': "恢复入站",
'unblock_out': "恢复出站"
}[op_type]
self.status_label.setText(f"{
op_name}...")
self.worker = FirewallWorker(self.files_to_process, op_type)
self.worker.progress.connect(self.update_progress)
self.worker.message.connect(self.update_status)
self.worker.finished.connect(self.on_operation_finished)
self.worker.start()
def update_progress(self, value):
base_progress = 100 * self.current_operation_index // len(self.operations)
current_op_progress = value // len(self.operations)
self.progress_bar.setValue(base_progress + current_op_progress)
def update_status(self, message):
self.status_label.setText(message)
def on_operation_finished(self):
self.current_operation_index += 1
self.start_next_operation()
def on_operations_finished(self):
self.progress_bar.setVisible(False)
self.status_label.setText("✅ 所有操作已完成")
QMessageBox.information(
self,
"完成",
"所有防火墙操作已成功执行",
QMessageBox.Ok
)
def open_firewall_settings(self):
try:
subprocess.run(['wf.msc'], shell=True)
except Exception as e:
QMessageBox.critical(
self,
"错误",
f"无法打开防火墙设置: {
str(e)}",
QMessageBox.Ok
)
def closeEvent(self, event):
if self.worker and self.worker.isRunning():
self.worker.stop()
self.worker.wait()
event.accept()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyle('Fusion')
font = QFont("Microsoft YaHei", 9)
app.setFont(font)
window = FirewallApp()
window.show()
sys.exit(app.exec_())
💡 总结与拓展
项目亮点
工程化设计:采用MVC模式分离业务逻辑与UI
防御式编程:完善的异常处理和边界检测
用户体验:符合Windows操作习惯的交互设计
改进方向
增加规则导入/导出功能
实现规则持久化存储
添加网络流量监控模块
🚀 技术延伸:本项目的核心思路可应用于:
企业级软件权限管理系统
自动化运维工具开发
安全审计平台建设
📚 参考资料
Microsoft Docs – Netsh Command Syntax
PyQt5 Official Documentation
Windows Security Center API
原创声明:本文代码100%原创,转载请注明出处!如有技术问题欢迎在评论区交流~
















暂无评论内容