1148 lines
40 KiB
HTML
1148 lines
40 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>防火墙管理控制台</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
:root {
|
|
--bg-primary: #0a0e27;
|
|
--bg-secondary: #151932;
|
|
--bg-card: #1a1f3a;
|
|
--bg-hover: #242a4a;
|
|
--text-primary: #ffffff;
|
|
--text-secondary: #a8b2d1;
|
|
--text-muted: #64748b;
|
|
--accent: #3b82f6;
|
|
--accent-hover: #2563eb;
|
|
--success: #10b981;
|
|
--danger: #ef4444;
|
|
--warning: #f59e0b;
|
|
--border: #2d3561;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background: var(--bg-primary);
|
|
color: var(--text-primary);
|
|
min-height: 100vh;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
padding: 20px;
|
|
}
|
|
|
|
.header {
|
|
background: var(--bg-secondary);
|
|
padding: 24px 32px;
|
|
border-radius: 16px;
|
|
margin-bottom: 32px;
|
|
box-shadow: 0 4px 24px rgba(0,0,0,0.3);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
backdrop-filter: blur(10px);
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.header h1 {
|
|
font-size: 28px;
|
|
font-weight: 600;
|
|
background: linear-gradient(135deg, #3b82f6 0%, #60a5fa 100%);
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
}
|
|
|
|
.stats {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
gap: 20px;
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.stat-card {
|
|
background: var(--bg-card);
|
|
padding: 24px;
|
|
border-radius: 12px;
|
|
border: 1px solid var(--border);
|
|
transition: all 0.3s ease;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.stat-card::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
height: 4px;
|
|
background: linear-gradient(90deg, var(--accent) 0%, #60a5fa 100%);
|
|
transform: translateX(-100%);
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.stat-card:hover::before {
|
|
transform: translateX(0);
|
|
}
|
|
|
|
.stat-card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 32px rgba(59, 130, 246, 0.2);
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 36px;
|
|
font-weight: 700;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.stat-label {
|
|
color: var(--text-secondary);
|
|
font-size: 14px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.controls {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 24px;
|
|
flex-wrap: wrap;
|
|
gap: 16px;
|
|
}
|
|
|
|
.search-box {
|
|
flex: 1;
|
|
max-width: 400px;
|
|
position: relative;
|
|
}
|
|
|
|
.search-box input {
|
|
width: 100%;
|
|
padding: 12px 48px 12px 20px;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-primary);
|
|
font-size: 14px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.search-box input:focus {
|
|
outline: none;
|
|
border-color: var(--accent);
|
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
}
|
|
|
|
.search-icon {
|
|
position: absolute;
|
|
right: 16px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.filter-buttons {
|
|
display: flex;
|
|
gap: 12px;
|
|
}
|
|
|
|
.filter-btn {
|
|
padding: 8px 16px;
|
|
background: var(--bg-card);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.filter-btn:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.filter-btn.active {
|
|
background: var(--accent);
|
|
color: white;
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
.btn-primary {
|
|
padding: 12px 24px;
|
|
background: linear-gradient(135deg, var(--accent) 0%, #2563eb 100%);
|
|
border: none;
|
|
border-radius: 8px;
|
|
color: white;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
box-shadow: 0 4px 16px rgba(59, 130, 246, 0.3);
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 24px rgba(59, 130, 246, 0.4);
|
|
}
|
|
|
|
.rules-table {
|
|
background: var(--bg-card);
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
border: 1px solid var(--border);
|
|
box-shadow: 0 4px 24px rgba(0,0,0,0.2);
|
|
}
|
|
|
|
.table-header {
|
|
display: grid;
|
|
grid-template-columns: 40px 2fr 1fr 1fr 100px 100px 120px 100px 100px 60px;
|
|
padding: 16px 24px;
|
|
background: var(--bg-secondary);
|
|
border-bottom: 1px solid var(--border);
|
|
font-weight: 600;
|
|
font-size: 13px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.rule-row {
|
|
display: grid;
|
|
grid-template-columns: 40px 2fr 1fr 1fr 100px 100px 120px 100px 100px 60px;
|
|
padding: 16px 24px;
|
|
border-bottom: 1px solid var(--border);
|
|
transition: all 0.3s ease;
|
|
cursor: pointer;
|
|
align-items: center;
|
|
}
|
|
|
|
.rule-row:hover {
|
|
background: var(--bg-hover);
|
|
transform: translateX(4px);
|
|
}
|
|
|
|
.rule-row:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.checkbox {
|
|
width: 20px;
|
|
height: 20px;
|
|
accent-color: var(--accent);
|
|
}
|
|
|
|
.rule-name {
|
|
font-weight: 500;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.rule-program {
|
|
color: var(--text-secondary);
|
|
font-size: 13px;
|
|
}
|
|
|
|
.status-badge {
|
|
padding: 4px 12px;
|
|
border-radius: 20px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
display: inline-block;
|
|
}
|
|
|
|
.status-enabled {
|
|
background: rgba(16, 185, 129, 0.2);
|
|
color: var(--success);
|
|
}
|
|
|
|
.status-disabled {
|
|
background: rgba(239, 68, 68, 0.2);
|
|
color: var(--danger);
|
|
}
|
|
|
|
.direction-badge {
|
|
padding: 4px 12px;
|
|
border-radius: 6px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.direction-in {
|
|
background: rgba(59, 130, 246, 0.2);
|
|
color: #60a5fa;
|
|
}
|
|
|
|
.direction-out {
|
|
background: rgba(245, 158, 11, 0.2);
|
|
color: var(--warning);
|
|
}
|
|
|
|
.actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.action-btn {
|
|
width: 32px;
|
|
height: 32px;
|
|
border: none;
|
|
background: transparent;
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
border-radius: 6px;
|
|
transition: all 0.3s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.action-btn:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--accent);
|
|
}
|
|
|
|
/* 模态框样式 */
|
|
.modal {
|
|
display: none;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.8);
|
|
backdrop-filter: blur(4px);
|
|
z-index: 1000;
|
|
animation: fadeIn 0.3s ease;
|
|
}
|
|
|
|
.modal.active {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
.modal-content {
|
|
background: var(--bg-card);
|
|
width: 90%;
|
|
max-width: 800px;
|
|
max-height: 90vh;
|
|
overflow-y: auto;
|
|
border-radius: 16px;
|
|
border: 1px solid var(--border);
|
|
animation: slideUp 0.3s ease;
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from {
|
|
transform: translateY(20px);
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
transform: translateY(0);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.modal-header {
|
|
padding: 24px 32px;
|
|
border-bottom: 1px solid var(--border);
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
background: var(--bg-secondary);
|
|
}
|
|
|
|
.modal-header h2 {
|
|
font-size: 20px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.close-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
border: none;
|
|
background: transparent;
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
border-radius: 8px;
|
|
font-size: 24px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.close-btn:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 32px;
|
|
}
|
|
|
|
.form-section {
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.form-section:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
margin-bottom: 16px;
|
|
color: var(--text-primary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
font-size: 14px;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.form-input, .form-select, .form-textarea {
|
|
width: 100%;
|
|
padding: 12px 16px;
|
|
background: var(--bg-secondary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-primary);
|
|
font-size: 14px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.form-input:focus, .form-select:focus, .form-textarea:focus {
|
|
outline: none;
|
|
border-color: var(--accent);
|
|
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
}
|
|
|
|
.form-textarea {
|
|
resize: vertical;
|
|
min-height: 100px;
|
|
}
|
|
|
|
.form-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 20px;
|
|
}
|
|
|
|
.radio-group, .checkbox-group {
|
|
display: flex;
|
|
gap: 16px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.radio-label, .checkbox-label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.service-list {
|
|
max-height: 200px;
|
|
overflow-y: auto;
|
|
background: var(--bg-secondary);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
padding: 12px;
|
|
}
|
|
|
|
.service-item {
|
|
padding: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
cursor: pointer;
|
|
border-radius: 4px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.service-item:hover {
|
|
background: var(--bg-hover);
|
|
}
|
|
|
|
.modal-footer {
|
|
padding: 24px 32px;
|
|
border-top: 1px solid var(--border);
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 12px;
|
|
background: var(--bg-secondary);
|
|
}
|
|
|
|
.btn-secondary {
|
|
padding: 12px 24px;
|
|
background: transparent;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
color: var(--text-secondary);
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background: var(--bg-hover);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
/* 滚动条样式 */
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: var(--bg-secondary);
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background: var(--border);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background: var(--accent);
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 1200px) {
|
|
.table-header, .rule-row {
|
|
grid-template-columns: 40px 2fr 1fr 80px 80px 100px 60px;
|
|
}
|
|
.rule-protocol, .rule-scope {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.stats {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
.controls {
|
|
flex-direction: column;
|
|
}
|
|
.search-box {
|
|
max-width: 100%;
|
|
}
|
|
.form-row {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<!-- 页头 -->
|
|
<div class="header">
|
|
<h1>🛡️ 防火墙管理控制台</h1>
|
|
<div class="header-actions">
|
|
<button class="btn-primary" onclick="openModal()">
|
|
<span>+</span>
|
|
<span>新建规则</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 统计卡片 -->
|
|
<div class="stats">
|
|
<div class="stat-card">
|
|
<div class="stat-value" id="totalRules">42</div>
|
|
<div class="stat-label">总规则数</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value" id="activeRules">38</div>
|
|
<div class="stat-label">活动规则</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value" id="inboundRules">18</div>
|
|
<div class="stat-label">入站规则</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="stat-value" id="outboundRules">24</div>
|
|
<div class="stat-label">出站规则</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 控制栏 -->
|
|
<div class="controls">
|
|
<div class="search-box">
|
|
<input type="text" placeholder="搜索规则名称、程序或端口..." id="searchInput">
|
|
<span class="search-icon">🔍</span>
|
|
</div>
|
|
<div class="filter-buttons">
|
|
<button class="filter-btn active" onclick="filterRules('all')">全部</button>
|
|
<button class="filter-btn" onclick="filterRules('inbound')">入站</button>
|
|
<button class="filter-btn" onclick="filterRules('outbound')">出站</button>
|
|
<button class="filter-btn" onclick="filterRules('enabled')">已启用</button>
|
|
<button class="filter-btn" onclick="filterRules('disabled')">已禁用</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 规则表格 -->
|
|
<div class="rules-table">
|
|
<div class="table-header">
|
|
<div></div>
|
|
<div>名称</div>
|
|
<div>程序</div>
|
|
<div>协议</div>
|
|
<div>端口</div>
|
|
<div>远程端口</div>
|
|
<div>作用域</div>
|
|
<div>方向</div>
|
|
<div>状态</div>
|
|
<div>操作</div>
|
|
</div>
|
|
<div id="rulesContainer">
|
|
<!-- 规则将通过JavaScript动态生成 -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 新建/编辑规则模态框 -->
|
|
<div class="modal" id="ruleModal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h2 id="modalTitle">新建防火墙规则</h2>
|
|
<button class="close-btn" onclick="closeModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<!-- 基本信息 -->
|
|
<div class="form-section">
|
|
<h3 class="section-title">📋 基本信息</h3>
|
|
<div class="form-group">
|
|
<label class="form-label">规则名称</label>
|
|
<input type="text" class="form-input" id="ruleName" placeholder="输入规则名称">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">描述</label>
|
|
<textarea class="form-textarea" id="ruleDescription" placeholder="输入规则描述(可选)"></textarea>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label">规则类型</label>
|
|
<select class="form-select" id="ruleType">
|
|
<option value="program">程序</option>
|
|
<option value="port">端口</option>
|
|
<option value="predefined">预定义</option>
|
|
<option value="custom">自定义</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">方向</label>
|
|
<div class="radio-group">
|
|
<label class="radio-label">
|
|
<input type="radio" name="direction" value="inbound" checked>
|
|
入站
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" name="direction" value="outbound">
|
|
出站
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 程序设置 -->
|
|
<div class="form-section">
|
|
<h3 class="section-title">💻 程序设置</h3>
|
|
<div class="form-group">
|
|
<label class="form-label">程序路径</label>
|
|
<input type="text" class="form-input" id="programPath" placeholder="例如:C:\Program Files\MyApp\app.exe">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">应用于服务</label>
|
|
<div class="checkbox-group">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="applyToAllServices">
|
|
应用于所有程序和服务
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="applyToServices">
|
|
仅应用于服务
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">选择服务</label>
|
|
<div class="service-list">
|
|
<div class="service-item">
|
|
<input type="checkbox" id="service1">
|
|
<label for="service1">Windows Update</label>
|
|
</div>
|
|
<div class="service-item">
|
|
<input type="checkbox" id="service2">
|
|
<label for="service2">Windows Defender</label>
|
|
</div>
|
|
<div class="service-item">
|
|
<input type="checkbox" id="service3">
|
|
<label for="service3">Remote Desktop</label>
|
|
</div>
|
|
<div class="service-item">
|
|
<input type="checkbox" id="service4">
|
|
<label for="service4">SQL Server</label>
|
|
</div>
|
|
<div class="service-item">
|
|
<input type="checkbox" id="service5">
|
|
<label for="service5">IIS</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 协议和端口 -->
|
|
<div class="form-section">
|
|
<h3 class="section-title">🔌 协议和端口</h3>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label">协议类型</label>
|
|
<select class="form-select" id="protocolType">
|
|
<option value="any">任意</option>
|
|
<option value="tcp">TCP</option>
|
|
<option value="udp">UDP</option>
|
|
<option value="icmpv4">ICMPv4</option>
|
|
<option value="icmpv6">ICMPv6</option>
|
|
<option value="custom">自定义</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">协议编号</label>
|
|
<input type="number" class="form-input" id="protocolNumber" placeholder="0-255" disabled>
|
|
</div>
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label">本地端口</label>
|
|
<input type="text" class="form-input" id="localPort" placeholder="例如:80, 443, 1000-2000">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">远程端口</label>
|
|
<input type="text" class="form-input" id="remotePort" placeholder="例如:80, 443, 1000-2000">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 作用域 -->
|
|
<div class="form-section">
|
|
<h3 class="section-title">🌐 作用域</h3>
|
|
<div class="form-group">
|
|
<label class="form-label">本地IP地址</label>
|
|
<div class="radio-group">
|
|
<label class="radio-label">
|
|
<input type="radio" name="localIP" value="any" checked>
|
|
任何IP地址
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" name="localIP" value="specific">
|
|
指定IP地址
|
|
</label>
|
|
</div>
|
|
<input type="text" class="form-input" id="localIPList" placeholder="例如:192.168.1.0/24" style="margin-top: 10px; display: none;">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">远程IP地址</label>
|
|
<div class="radio-group">
|
|
<label class="radio-label">
|
|
<input type="radio" name="remoteIP" value="any" checked>
|
|
任何IP地址
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" name="remoteIP" value="specific">
|
|
指定IP地址
|
|
</label>
|
|
</div>
|
|
<input type="text" class="form-input" id="remoteIPList" placeholder="例如:10.0.0.0/8" style="margin-top: 10px; display: none;">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 高级设置 -->
|
|
<div class="form-section">
|
|
<h3 class="section-title">⚙️ 高级设置</h3>
|
|
<div class="form-group">
|
|
<label class="form-label">配置文件</label>
|
|
<div class="checkbox-group">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="profileDomain" checked>
|
|
域
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="profilePrivate" checked>
|
|
专用
|
|
</label>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="profilePublic" checked>
|
|
公用
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">用户和计算机</label>
|
|
<div class="radio-group">
|
|
<label class="radio-label">
|
|
<input type="radio" name="users" value="all" checked>
|
|
所有用户和计算机
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" name="users" value="specific">
|
|
指定用户或组
|
|
</label>
|
|
</div>
|
|
<input type="text" class="form-input" id="userList" placeholder="输入用户或组名称" style="margin-top: 10px; display: none;">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">操作</label>
|
|
<div class="radio-group">
|
|
<label class="radio-label">
|
|
<input type="radio" name="action" value="allow" checked>
|
|
允许连接
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" name="action" value="block">
|
|
阻止连接
|
|
</label>
|
|
<label class="radio-label">
|
|
<input type="radio" name="action" value="secure">
|
|
允许安全连接
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn-secondary" onclick="closeModal()">取消</button>
|
|
<button class="btn-primary" onclick="saveRule()">保存规则</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// 模拟防火墙规则数据
|
|
let rules = [
|
|
{
|
|
id: 1,
|
|
name: "Chrome 浏览器",
|
|
program: "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
protocol: "TCP",
|
|
port: "80, 443",
|
|
remotePort: "任意",
|
|
scope: "任意",
|
|
direction: "outbound",
|
|
status: "enabled",
|
|
action: "允许"
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "远程桌面 - 用户模式 (TCP-In)",
|
|
program: "系统",
|
|
protocol: "TCP",
|
|
port: "3389",
|
|
remotePort: "任意",
|
|
scope: "任意",
|
|
direction: "inbound",
|
|
status: "enabled",
|
|
action: "允许"
|
|
},
|
|
{
|
|
id: 3,
|
|
name: "Windows Media Player",
|
|
program: "C:\\Program Files\\Windows Media Player\\wmplayer.exe",
|
|
protocol: "UDP",
|
|
port: "554, 8554",
|
|
remotePort: "任意",
|
|
scope: "本地子网",
|
|
direction: "inbound",
|
|
status: "disabled",
|
|
action: "允许"
|
|
},
|
|
{
|
|
id: 4,
|
|
name: "SQL Server",
|
|
program: "C:\\Program Files\\Microsoft SQL Server\\MSSQL\\Binn\\sqlservr.exe",
|
|
protocol: "TCP",
|
|
port: "1433",
|
|
remotePort: "任意",
|
|
scope: "192.168.1.0/24",
|
|
direction: "inbound",
|
|
status: "enabled",
|
|
action: "允许"
|
|
},
|
|
{
|
|
id: 5,
|
|
name: "核心网络 - DHCP (Out)",
|
|
program: "系统",
|
|
protocol: "UDP",
|
|
port: "68",
|
|
remotePort: "67",
|
|
scope: "任意",
|
|
direction: "outbound",
|
|
status: "enabled",
|
|
action: "允许"
|
|
}
|
|
];
|
|
|
|
let currentFilter = 'all';
|
|
let editingRule = null;
|
|
|
|
// 渲染规则列表
|
|
function renderRules() {
|
|
const container = document.getElementById('rulesContainer');
|
|
container.innerHTML = '';
|
|
|
|
let filteredRules = rules;
|
|
|
|
// 应用过滤器
|
|
if (currentFilter === 'inbound') {
|
|
filteredRules = rules.filter(r => r.direction === 'inbound');
|
|
} else if (currentFilter === 'outbound') {
|
|
filteredRules = rules.filter(r => r.direction === 'outbound');
|
|
} else if (currentFilter === 'enabled') {
|
|
filteredRules = rules.filter(r => r.status === 'enabled');
|
|
} else if (currentFilter === 'disabled') {
|
|
filteredRules = rules.filter(r => r.status === 'disabled');
|
|
}
|
|
|
|
// 应用搜索
|
|
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
|
if (searchTerm) {
|
|
filteredRules = filteredRules.filter(r =>
|
|
r.name.toLowerCase().includes(searchTerm) ||
|
|
r.program.toLowerCase().includes(searchTerm) ||
|
|
r.port.toLowerCase().includes(searchTerm)
|
|
);
|
|
}
|
|
|
|
filteredRules.forEach(rule => {
|
|
const row = document.createElement('div');
|
|
row.className = 'rule-row';
|
|
row.innerHTML = `
|
|
<div><input type="checkbox" class="checkbox"></div>
|
|
<div class="rule-name">${rule.name}</div>
|
|
<div class="rule-program">${rule.program}</div>
|
|
<div>${rule.protocol}</div>
|
|
<div>${rule.port}</div>
|
|
<div>${rule.remotePort}</div>
|
|
<div class="rule-scope">${rule.scope}</div>
|
|
<div><span class="direction-badge direction-${rule.direction === 'inbound' ? 'in' : 'out'}">${rule.direction === 'inbound' ? '入站' : '出站'}</span></div>
|
|
<div><span class="status-badge status-${rule.status}">${rule.status === 'enabled' ? '已启用' : '已禁用'}</span></div>
|
|
<div class="actions">
|
|
<button class="action-btn" onclick="editRule(${rule.id})" title="编辑">✏️</button>
|
|
<button class="action-btn" onclick="deleteRule(${rule.id})" title="删除">🗑️</button>
|
|
</div>
|
|
`;
|
|
row.onclick = (e) => {
|
|
if (!e.target.classList.contains('action-btn') && e.target.type !== 'checkbox') {
|
|
editRule(rule.id);
|
|
}
|
|
};
|
|
container.appendChild(row);
|
|
});
|
|
|
|
updateStats();
|
|
}
|
|
|
|
// 更新统计信息
|
|
function updateStats() {
|
|
document.getElementById('totalRules').textContent = rules.length;
|
|
document.getElementById('activeRules').textContent = rules.filter(r => r.status === 'enabled').length;
|
|
document.getElementById('inboundRules').textContent = rules.filter(r => r.direction === 'inbound').length;
|
|
document.getElementById('outboundRules').textContent = rules.filter(r => r.direction === 'outbound').length;
|
|
}
|
|
|
|
// 过滤规则
|
|
function filterRules(filter) {
|
|
currentFilter = filter;
|
|
document.querySelectorAll('.filter-btn').forEach(btn => {
|
|
btn.classList.remove('active');
|
|
});
|
|
event.target.classList.add('active');
|
|
renderRules();
|
|
}
|
|
|
|
// 打开模态框
|
|
function openModal() {
|
|
document.getElementById('ruleModal').classList.add('active');
|
|
document.getElementById('modalTitle').textContent = '新建防火墙规则';
|
|
editingRule = null;
|
|
clearForm();
|
|
}
|
|
|
|
// 关闭模态框
|
|
function closeModal() {
|
|
document.getElementById('ruleModal').classList.remove('active');
|
|
editingRule = null;
|
|
}
|
|
|
|
// 编辑规则
|
|
function editRule(id) {
|
|
const rule = rules.find(r => r.id === id);
|
|
if (rule) {
|
|
editingRule = rule;
|
|
document.getElementById('modalTitle').textContent = '编辑防火墙规则';
|
|
document.getElementById('ruleName').value = rule.name;
|
|
document.getElementById('programPath').value = rule.program;
|
|
document.getElementById('protocolType').value = rule.protocol.toLowerCase();
|
|
document.getElementById('localPort').value = rule.port;
|
|
document.getElementById('remotePort').value = rule.remotePort === '任意' ? '' : rule.remotePort;
|
|
document.querySelector(`input[name="direction"][value="${rule.direction}"]`).checked = true;
|
|
document.querySelector(`input[name="action"][value="allow"]`).checked = rule.action === '允许';
|
|
document.getElementById('ruleModal').classList.add('active');
|
|
}
|
|
}
|
|
|
|
// 删除规则
|
|
function deleteRule(id) {
|
|
if (confirm('确定要删除这条规则吗?')) {
|
|
rules = rules.filter(r => r.id !== id);
|
|
renderRules();
|
|
}
|
|
}
|
|
|
|
// 保存规则
|
|
function saveRule() {
|
|
const name = document.getElementById('ruleName').value;
|
|
const program = document.getElementById('programPath').value || '系统';
|
|
const protocol = document.getElementById('protocolType').value.toUpperCase();
|
|
const port = document.getElementById('localPort').value || '任意';
|
|
const remotePort = document.getElementById('remotePort').value || '任意';
|
|
const direction = document.querySelector('input[name="direction"]:checked').value;
|
|
const action = document.querySelector('input[name="action"]:checked').value === 'allow' ? '允许' : '阻止';
|
|
|
|
if (!name) {
|
|
alert('请输入规则名称');
|
|
return;
|
|
}
|
|
|
|
if (editingRule) {
|
|
// 更新现有规则
|
|
editingRule.name = name;
|
|
editingRule.program = program;
|
|
editingRule.protocol = protocol;
|
|
editingRule.port = port;
|
|
editingRule.remotePort = remotePort;
|
|
editingRule.direction = direction;
|
|
editingRule.action = action;
|
|
} else {
|
|
// 创建新规则
|
|
const newRule = {
|
|
id: Date.now(),
|
|
name,
|
|
program,
|
|
protocol,
|
|
port,
|
|
remotePort,
|
|
scope: '任意',
|
|
direction,
|
|
status: 'enabled',
|
|
action
|
|
};
|
|
rules.push(newRule);
|
|
}
|
|
|
|
renderRules();
|
|
closeModal();
|
|
}
|
|
|
|
// 清空表单
|
|
function clearForm() {
|
|
document.getElementById('ruleName').value = '';
|
|
document.getElementById('ruleDescription').value = '';
|
|
document.getElementById('programPath').value = '';
|
|
document.getElementById('protocolType').value = 'any';
|
|
document.getElementById('localPort').value = '';
|
|
document.getElementById('remotePort').value = '';
|
|
document.querySelector('input[name="direction"][value="inbound"]').checked = true;
|
|
document.querySelector('input[name="action"][value="allow"]').checked = true;
|
|
}
|
|
|
|
// 搜索功能
|
|
document.getElementById('searchInput').addEventListener('input', renderRules);
|
|
|
|
// 协议类型变化时的处理
|
|
document.getElementById('protocolType').addEventListener('change', function() {
|
|
const protocolNumber = document.getElementById('protocolNumber');
|
|
if (this.value === 'custom') {
|
|
protocolNumber.disabled = false;
|
|
} else {
|
|
protocolNumber.disabled = true;
|
|
protocolNumber.value = '';
|
|
}
|
|
});
|
|
|
|
// IP地址选择的处理
|
|
document.querySelectorAll('input[name="localIP"]').forEach(radio => {
|
|
radio.addEventListener('change', function() {
|
|
const localIPList = document.getElementById('localIPList');
|
|
if (this.value === 'specific') {
|
|
localIPList.style.display = 'block';
|
|
} else {
|
|
localIPList.style.display = 'none';
|
|
}
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('input[name="remoteIP"]').forEach(radio => {
|
|
radio.addEventListener('change', function() {
|
|
const remoteIPList = document.getElementById('remoteIPList');
|
|
if (this.value === 'specific') {
|
|
remoteIPList.style.display = 'block';
|
|
} else {
|
|
remoteIPList.style.display = 'none';
|
|
}
|
|
});
|
|
});
|
|
|
|
// 用户选择的处理
|
|
document.querySelectorAll('input[name="users"]').forEach(radio => {
|
|
radio.addEventListener('change', function() {
|
|
const userList = document.getElementById('userList');
|
|
if (this.value === 'specific') {
|
|
userList.style.display = 'block';
|
|
} else {
|
|
userList.style.display = 'none';
|
|
}
|
|
});
|
|
});
|
|
|
|
// 点击模态框外部关闭
|
|
document.getElementById('ruleModal').addEventListener('click', function(e) {
|
|
if (e.target === this) {
|
|
closeModal();
|
|
}
|
|
});
|
|
|
|
// 初始化
|
|
renderRules();
|
|
</script>
|
|
</body>
|
|
</html> |