Initial commit — SETEC LABS Manager (Setec_CDM)
Flask-based VPS management panel with SSH remote command execution. Includes E2E encrypted SSH tunnel (AES-256-GCM + Go agent), setup wizard, security hardening tools, DNS management, firewall configs, monitoring, backup, and .sec patch update system. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
990
setec-web/templates/firewall.html
Normal file
990
setec-web/templates/firewall.html
Normal file
@@ -0,0 +1,990 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Firewall{% endblock %}
|
||||
{% block content %}
|
||||
<h1>[|] Firewall Manager</h1>
|
||||
|
||||
<!-- Tab navigation -->
|
||||
<div class="toolbar" id="tabs">
|
||||
<button class="btn" onclick="showTab('dashboard')" id="tab-dashboard">Dashboard</button>
|
||||
<button class="btn" onclick="showTab('ufw')" id="tab-ufw">UFW</button>
|
||||
<button class="btn" onclick="showTab('iptables')" id="tab-iptables">iptables</button>
|
||||
<button class="btn" onclick="showTab('nftables')" id="tab-nftables">nftables</button>
|
||||
<button class="btn" onclick="showTab('firewalld')" id="tab-firewalld">firewalld</button>
|
||||
<button class="btn" onclick="showTab('csf')" id="tab-csf">CSF</button>
|
||||
<button class="btn" onclick="showTab('ufw2ip')" id="tab-ufw2ip">UFW → IP</button>
|
||||
<button class="btn" onclick="showTab('ip2ufw')" id="tab-ip2ufw">IP → UFW</button>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ DASHBOARD TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-dashboard">
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Firewall Detection</div>
|
||||
<div id="fw-detect" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwDetect()">Detect Firewalls</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Open Ports</div>
|
||||
<div id="fw-ports" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwPorts()">Scan Ports</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Active Connections</div>
|
||||
<div id="fw-conns" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwConns()">Refresh</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Connection Stats by State</div>
|
||||
<div id="fw-connstats" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwConnStats()">Refresh</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Top Connections by IP</div>
|
||||
<div id="fw-topip" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwTopIPs()">Refresh</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Recent Blocked / Dropped</div>
|
||||
<div id="fw-blocked" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwBlocked()">Refresh</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Firewall Log</div>
|
||||
<div id="fw-log" class="output" style="max-height:400px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwLog()">Load Log</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ UFW TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-ufw" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-title">UFW Status</div>
|
||||
<div id="ufw-status" class="output" style="max-height:400px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="ufwStatus()">Refresh</button>
|
||||
<button class="btn btn-warn" onclick="ufwEnable()">Enable UFW</button>
|
||||
<button class="btn btn-danger" onclick="ufwDisable()">Disable UFW</button>
|
||||
<button class="btn" onclick="ufwNumbered()">Numbered Rules</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Add Rule</div>
|
||||
<label>Rule (e.g. "allow 8080/tcp", "deny from 1.2.3.4")</label>
|
||||
<input type="text" id="ufw-rule" placeholder="allow 443/tcp" style="width:100%;">
|
||||
<button class="btn" onclick="ufwAdd()" style="margin-top:8px;">Add Rule</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Delete Rule</div>
|
||||
<label>Rule to delete (e.g. "allow 8080/tcp")</label>
|
||||
<input type="text" id="ufw-del-rule" placeholder="allow 8080/tcp" style="width:100%;">
|
||||
<button class="btn btn-danger" onclick="ufwDel()" style="margin-top:8px;">Delete Rule</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Presets</div>
|
||||
<button class="btn" onclick="ufwPreset('webserver')">Web Server (80, 443)</button>
|
||||
<button class="btn" onclick="ufwPreset('mailserver')">Mail Server (25, 465, 587, 993)</button>
|
||||
<button class="btn btn-danger" onclick="ufwPreset('lockdown')">Lockdown (SSH only)</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Defaults</div>
|
||||
<div id="ufw-defaults" class="output" style="max-height:150px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="ufwDefault('deny','incoming')">Default Deny In</button>
|
||||
<button class="btn" onclick="ufwDefault('allow','outgoing')">Default Allow Out</button>
|
||||
<button class="btn btn-danger" onclick="ufwDefault('deny','outgoing')">Default Deny Out</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">UFW Application Profiles</div>
|
||||
<div id="ufw-apps" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="ufwAppList()">List App Profiles</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">UFW Log</div>
|
||||
<div id="ufw-log" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="ufwLog()">View Log</button>
|
||||
<button class="btn" onclick="ufwLogLevel('on')">Logging On</button>
|
||||
<button class="btn" onclick="ufwLogLevel('high')">Logging High</button>
|
||||
<button class="btn btn-danger" onclick="ufwLogLevel('off')">Logging Off</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ IPTABLES TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-iptables" style="display:none;">
|
||||
<div id="ipt-not-installed" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-title">iptables</div>
|
||||
<p style="color:#888;margin-bottom:10px;">iptables is the traditional Linux packet filter. It is usually pre-installed.</p>
|
||||
<div id="ipt-install-out" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<button class="btn btn-warn" onclick="iptInstall()">Install iptables</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipt-main">
|
||||
<div class="card">
|
||||
<div class="card-title">iptables Rules (filter)</div>
|
||||
<div id="ipt-rules" class="output" style="max-height:500px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="iptList()">Filter Table</button>
|
||||
<button class="btn" onclick="iptListNat()">NAT Table</button>
|
||||
<button class="btn" onclick="iptListMangle()">Mangle Table</button>
|
||||
<button class="btn" onclick="iptCounters()">Counters</button>
|
||||
<button class="btn" onclick="iptIp6()">IPv6 Rules</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Add Rule</div>
|
||||
<label>Chain</label>
|
||||
<select id="ipt-chain" style="width:120px;">
|
||||
<option>INPUT</option>
|
||||
<option>OUTPUT</option>
|
||||
<option>FORWARD</option>
|
||||
</select>
|
||||
<label>Rule (e.g. "-p tcp --dport 80 -j ACCEPT")</label>
|
||||
<input type="text" id="ipt-rule" placeholder="-p tcp --dport 80 -j ACCEPT" style="width:100%;">
|
||||
<div style="margin-top:8px;">
|
||||
<button class="btn" onclick="iptAdd()">Append Rule</button>
|
||||
<label style="display:inline;">Position</label>
|
||||
<input type="number" id="ipt-pos" value="1" style="width:50px;">
|
||||
<button class="btn" onclick="iptInsert()">Insert at Position</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Delete Rule</div>
|
||||
<label>Chain</label>
|
||||
<select id="ipt-del-chain" style="width:120px;">
|
||||
<option>INPUT</option>
|
||||
<option>OUTPUT</option>
|
||||
<option>FORWARD</option>
|
||||
</select>
|
||||
<label>Rule Number</label>
|
||||
<input type="number" id="ipt-del-num" value="1" style="width:80px;">
|
||||
<button class="btn btn-danger" onclick="iptDelete()" style="margin-top:8px;">Delete Rule</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Chain Policy</div>
|
||||
<label>Chain</label>
|
||||
<select id="ipt-pol-chain" style="width:120px;">
|
||||
<option>INPUT</option>
|
||||
<option>OUTPUT</option>
|
||||
<option>FORWARD</option>
|
||||
</select>
|
||||
<label>Policy</label>
|
||||
<select id="ipt-pol-target" style="width:120px;">
|
||||
<option>ACCEPT</option>
|
||||
<option>DROP</option>
|
||||
</select>
|
||||
<button class="btn btn-warn" onclick="iptPolicy()" style="margin-top:8px;">Set Policy</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Quick Actions</div>
|
||||
<div style="margin-bottom:8px;">
|
||||
<label>IP Address</label>
|
||||
<input type="text" id="ipt-ip" placeholder="1.2.3.4" style="width:160px;">
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<button class="btn btn-danger" onclick="iptBlockIP()">Block IP</button>
|
||||
<button class="btn" onclick="iptUnblockIP()">Unblock IP</button>
|
||||
<button class="btn" onclick="iptListBlocked()">Show Blocked</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Persistence</div>
|
||||
<div id="ipt-persist" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn btn-warn" onclick="iptSave()">Save Rules</button>
|
||||
<button class="btn" onclick="iptRestore()">Restore Saved</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Flush</div>
|
||||
<div id="ipt-flush-out" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn btn-danger" onclick="iptFlush()">Flush All Rules</button>
|
||||
<button class="btn" onclick="iptZero()">Zero Counters</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">iptables Log</div>
|
||||
<div id="ipt-log" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="iptLog()">View Log</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ NFTABLES TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-nftables" style="display:none;">
|
||||
<div id="nft-not-installed" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-title">nftables</div>
|
||||
<p style="color:#888;margin-bottom:10px;">nftables is the modern replacement for iptables. Provides better performance and a cleaner syntax.</p>
|
||||
<div id="nft-install-out" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<button class="btn btn-warn" onclick="nftInstall()">Install nftables</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="nft-main">
|
||||
<div class="card">
|
||||
<div class="card-title">nftables Ruleset</div>
|
||||
<div id="nft-rules" class="output" style="max-height:500px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="nftList()">Full Ruleset</button>
|
||||
<button class="btn" onclick="nftTables()">Tables</button>
|
||||
<button class="btn" onclick="nftCounters()">Counters</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">List Chains</div>
|
||||
<div id="nft-chains" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<label>Table (e.g. "inet filter")</label>
|
||||
<input type="text" id="nft-table" value="inet filter" style="width:200px;">
|
||||
<button class="btn" onclick="nftChains()" style="margin-top:8px;">List Chains</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Add Rule</div>
|
||||
<label>Table</label>
|
||||
<input type="text" id="nft-add-table" value="inet filter" style="width:180px;">
|
||||
<label>Chain</label>
|
||||
<input type="text" id="nft-add-chain" value="input" style="width:180px;">
|
||||
<label>Rule (e.g. "tcp dport 80 accept")</label>
|
||||
<input type="text" id="nft-add-rule" placeholder="tcp dport 80 accept" style="width:100%;">
|
||||
<button class="btn" onclick="nftAddRule()" style="margin-top:8px;">Add Rule</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Delete Rule</div>
|
||||
<label>Table</label>
|
||||
<input type="text" id="nft-del-table" value="inet filter" style="width:180px;">
|
||||
<label>Chain</label>
|
||||
<input type="text" id="nft-del-chain" value="input" style="width:180px;">
|
||||
<label>Handle Number</label>
|
||||
<input type="number" id="nft-del-handle" style="width:80px;">
|
||||
<button class="btn btn-danger" onclick="nftDelRule()" style="margin-top:8px;">Delete Rule</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Create Table / Chain</div>
|
||||
<label>Family</label>
|
||||
<select id="nft-family" style="width:100px;">
|
||||
<option>inet</option>
|
||||
<option>ip</option>
|
||||
<option>ip6</option>
|
||||
<option>bridge</option>
|
||||
</select>
|
||||
<label>Table Name</label>
|
||||
<input type="text" id="nft-new-table" placeholder="mytable" style="width:150px;">
|
||||
<button class="btn" onclick="nftCreateTable()" style="margin-top:8px;">Create Table</button>
|
||||
<div style="margin-top:10px;border-top:1px solid #333;padding-top:8px;">
|
||||
<label>Chain Name</label>
|
||||
<input type="text" id="nft-new-chain" placeholder="mychain" style="width:150px;">
|
||||
<label>Hook</label>
|
||||
<select id="nft-hook" style="width:100px;">
|
||||
<option>input</option>
|
||||
<option>output</option>
|
||||
<option>forward</option>
|
||||
<option>prerouting</option>
|
||||
<option>postrouting</option>
|
||||
</select>
|
||||
<button class="btn" onclick="nftCreateChain()" style="margin-top:8px;">Create Chain</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Persistence</div>
|
||||
<div id="nft-persist" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn btn-warn" onclick="nftSave()">Save Ruleset</button>
|
||||
<button class="btn" onclick="nftRestore()">Restore Saved</button>
|
||||
<button class="btn" onclick="nftConfig()">View Config File</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Flush</div>
|
||||
<div id="nft-flush-out" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<button class="btn btn-danger" onclick="nftFlush()">Flush All</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ FIREWALLD TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-firewalld" style="display:none;">
|
||||
<div id="fwd-not-installed" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-title">firewalld</div>
|
||||
<p style="color:#888;margin-bottom:10px;">firewalld is a zone-based firewall manager. Common on RHEL/CentOS but also available on Debian/Ubuntu.</p>
|
||||
<div id="fwd-install-out" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<button class="btn btn-warn" onclick="fwdInstall()">Install firewalld</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="fwd-main">
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">firewalld Status</div>
|
||||
<div id="fwd-status" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="fwdStatus()">Refresh</button>
|
||||
<button class="btn btn-warn" onclick="fwdReload()">Reload</button>
|
||||
<button class="btn btn-danger" onclick="fwdPanicOn()">Panic On</button>
|
||||
<button class="btn" onclick="fwdPanicOff()">Panic Off</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Zones</div>
|
||||
<div id="fwd-zones" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwdZones()">List Zones</button>
|
||||
<div style="margin-top:8px;">
|
||||
<label>Zone</label>
|
||||
<input type="text" id="fwd-zone" value="public" style="width:120px;">
|
||||
<button class="btn" onclick="fwdZoneInfo()">Zone Info</button>
|
||||
<button class="btn btn-warn" onclick="fwdSetDefault()">Set as Default</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Services</div>
|
||||
<div id="fwd-services" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<label>Service (e.g. http, https, ssh, smtp)</label>
|
||||
<input type="text" id="fwd-service" placeholder="http" style="width:150px;">
|
||||
<div class="toolbar" style="margin-top:8px;">
|
||||
<button class="btn" onclick="fwdServicesList()">List Available</button>
|
||||
<button class="btn btn-warn" onclick="fwdAddService()">Add Service</button>
|
||||
<button class="btn btn-danger" onclick="fwdRemoveService()">Remove Service</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Ports</div>
|
||||
<div id="fwd-ports" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<label>Port (e.g. 8080/tcp)</label>
|
||||
<input type="text" id="fwd-port" placeholder="8080/tcp" style="width:150px;">
|
||||
<div class="toolbar" style="margin-top:8px;">
|
||||
<button class="btn btn-warn" onclick="fwdAddPort()">Add Port</button>
|
||||
<button class="btn btn-danger" onclick="fwdRemovePort()">Remove Port</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Rich Rules</div>
|
||||
<div id="fwd-rich" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<label>Rich Rule</label>
|
||||
<input type="text" id="fwd-rich-rule" placeholder='rule family="ipv4" source address="1.2.3.4" drop' style="width:100%;">
|
||||
<div class="toolbar" style="margin-top:8px;">
|
||||
<button class="btn btn-warn" onclick="fwdAddRich()">Add Rich Rule</button>
|
||||
<button class="btn btn-danger" onclick="fwdRemoveRich()">Remove Rich Rule</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Block / Unblock IP</div>
|
||||
<div id="fwd-block" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<label>IP Address</label>
|
||||
<input type="text" id="fwd-ip" placeholder="1.2.3.4" style="width:160px;">
|
||||
<div class="toolbar" style="margin-top:8px;">
|
||||
<button class="btn btn-danger" onclick="fwdBlockIP()">Block IP</button>
|
||||
<button class="btn" onclick="fwdUnblockIP()">Unblock IP</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">firewalld Log</div>
|
||||
<div id="fwd-log" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="fwdLog()">View Log</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ CSF TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-csf" style="display:none;">
|
||||
<div id="csf-not-installed" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-title">CSF (ConfigServer Security & Firewall)</div>
|
||||
<p style="color:#888;margin-bottom:10px;">CSF is a stateful packet inspection firewall with login/intrusion detection (LFD). Popular on cPanel servers but works standalone.</p>
|
||||
<div id="csf-install-out" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<button class="btn btn-warn" onclick="csfInstall()">Install CSF</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="csf-main">
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">CSF Status</div>
|
||||
<div id="csf-status" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="csfStatus()">Refresh</button>
|
||||
<button class="btn btn-warn" onclick="csfStart()">Start</button>
|
||||
<button class="btn btn-danger" onclick="csfStop()">Stop (Flush)</button>
|
||||
<button class="btn" onclick="csfRestart()">Restart</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Test iptables Modules</div>
|
||||
<div id="csf-test" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="csfTest()">Run Test</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Rules</div>
|
||||
<div id="csf-rules" class="output" style="max-height:500px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="csfList()">List All Rules</button>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Allow / Deny IP</div>
|
||||
<div id="csf-ip-out" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<label>IP Address</label>
|
||||
<input type="text" id="csf-ip" placeholder="1.2.3.4" style="width:160px;">
|
||||
<label>Comment</label>
|
||||
<input type="text" id="csf-comment" placeholder="reason" style="width:200px;">
|
||||
<div class="toolbar" style="margin-top:8px;">
|
||||
<button class="btn" onclick="csfAllow()">Allow</button>
|
||||
<button class="btn btn-danger" onclick="csfDeny()">Deny</button>
|
||||
<button class="btn" onclick="csfRemove()">Remove</button>
|
||||
<button class="btn" onclick="csfGrep()">Search IP</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">Temporary Rules</div>
|
||||
<div id="csf-temp" class="output" style="max-height:200px;margin-bottom:10px;"></div>
|
||||
<label>TTL (seconds)</label>
|
||||
<input type="number" id="csf-ttl" value="3600" style="width:100px;">
|
||||
<div class="toolbar" style="margin-top:8px;">
|
||||
<button class="btn" onclick="csfTempAllow()">Temp Allow</button>
|
||||
<button class="btn btn-danger" onclick="csfTempDeny()">Temp Deny</button>
|
||||
<button class="btn" onclick="csfTempList()">List Temp Rules</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-2">
|
||||
<div class="card">
|
||||
<div class="card-title">Configuration</div>
|
||||
<div id="csf-config" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="csfConfig()">View Key Settings</button>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-title">LFD Log</div>
|
||||
<div id="csf-log" class="output" style="max-height:300px;margin-bottom:10px;"></div>
|
||||
<button class="btn" onclick="csfLog()">View Log</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ UFW → IPTABLES TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-ufw2ip" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-title">Migrate: UFW → iptables</div>
|
||||
<p style="color:#888;margin-bottom:15px;">
|
||||
This will disable UFW and switch to raw iptables management. Your existing firewall rules
|
||||
(which UFW manages via iptables under the hood) will be preserved and saved to
|
||||
<code>/etc/iptables/rules.v4</code>. iptables-persistent will be installed to ensure
|
||||
rules survive reboots.
|
||||
</p>
|
||||
<div style="margin-bottom:15px;padding:10px;border:1px solid #ffaa00;color:#ffaa00;">
|
||||
<strong>What happens:</strong><br>
|
||||
1. Current UFW/iptables state is backed up<br>
|
||||
2. UFW is disabled and its service stopped<br>
|
||||
3. The iptables rules that UFW generated are saved<br>
|
||||
4. iptables-persistent is installed for persistence<br>
|
||||
5. You manage rules directly via the iptables tab
|
||||
</div>
|
||||
<div id="m-ufw2ip-out" class="output" style="max-height:500px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="previewUfw2Ip()">Preview Current Rules</button>
|
||||
<button class="btn btn-danger" onclick="runUfw2Ip()">Migrate UFW → iptables</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════ IPTABLES → UFW TAB ═══════════════════════ -->
|
||||
<div class="tab-content" id="panel-ip2ufw" style="display:none;">
|
||||
<div class="card">
|
||||
<div class="card-title">Migrate: iptables → UFW</div>
|
||||
<p style="color:#888;margin-bottom:15px;">
|
||||
This will convert your iptables rules to UFW and enable UFW as the primary firewall frontend.
|
||||
Your current iptables rules are backed up before any changes. TCP/UDP ACCEPT rules on INPUT
|
||||
are automatically converted to UFW allow rules.
|
||||
</p>
|
||||
<div style="margin-bottom:15px;padding:10px;border:1px solid #ffaa00;color:#ffaa00;">
|
||||
<strong>What happens:</strong><br>
|
||||
1. Current iptables rules are backed up<br>
|
||||
2. UFW is installed (if not present) and reset<br>
|
||||
3. Default deny incoming / allow outgoing is set<br>
|
||||
4. iptables ACCEPT rules are converted to UFW allow rules<br>
|
||||
5. UFW is enabled, iptables-persistent is disabled<br>
|
||||
6. You manage rules via the UFW tab
|
||||
</div>
|
||||
<div id="m-ip2ufw-out" class="output" style="max-height:500px;margin-bottom:10px;"></div>
|
||||
<div class="toolbar">
|
||||
<button class="btn" onclick="previewIp2Ufw()">Preview Current Rules</button>
|
||||
<button class="btn btn-danger" onclick="runIp2Ufw()">Migrate iptables → UFW</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
// ── Tab switching ──
|
||||
function showTab(name) {
|
||||
document.querySelectorAll('.tab-content').forEach(el => el.style.display = 'none');
|
||||
document.querySelectorAll('#tabs .btn').forEach(el => el.style.background = '');
|
||||
document.getElementById('panel-' + name).style.display = 'block';
|
||||
document.getElementById('tab-' + name).style.background = '#1a2a1a';
|
||||
}
|
||||
showTab('dashboard');
|
||||
|
||||
// ── Dashboard ──
|
||||
async function fwDetect() {
|
||||
const r = await apiGet('/api/firewall/detect');
|
||||
showResult(r, 'fw-detect');
|
||||
}
|
||||
async function fwPorts() {
|
||||
const r = await apiGet('/api/firewall/ports');
|
||||
showResult(r, 'fw-ports');
|
||||
}
|
||||
async function fwConns() {
|
||||
const r = await apiGet('/api/firewall/connections');
|
||||
showResult(r, 'fw-conns');
|
||||
}
|
||||
async function fwConnStats() {
|
||||
const r = await apiGet('/api/firewall/connection-stats');
|
||||
showResult(r, 'fw-connstats');
|
||||
}
|
||||
async function fwTopIPs() {
|
||||
const r = await apiGet('/api/firewall/top-ips');
|
||||
showResult(r, 'fw-topip');
|
||||
}
|
||||
async function fwBlocked() {
|
||||
const r = await apiGet('/api/firewall/blocked');
|
||||
showResult(r, 'fw-blocked');
|
||||
}
|
||||
async function fwLog() {
|
||||
const r = await apiGet('/api/firewall/log');
|
||||
showResult(r, 'fw-log');
|
||||
}
|
||||
|
||||
// ── UFW ──
|
||||
async function ufwStatus() {
|
||||
const r = await apiGet('/api/security/firewall/status');
|
||||
showResult(r, 'ufw-status');
|
||||
}
|
||||
async function ufwNumbered() {
|
||||
const r = await apiGet('/api/firewall/ufw/numbered');
|
||||
showResult(r, 'ufw-status');
|
||||
}
|
||||
async function ufwEnable() {
|
||||
const r = await apiPost('/api/security/firewall/enable');
|
||||
showResult(r, 'ufw-status');
|
||||
}
|
||||
async function ufwDisable() {
|
||||
if (!confirm('Disable UFW?')) return;
|
||||
const r = await apiPost('/api/security/firewall/disable');
|
||||
showResult(r, 'ufw-status');
|
||||
}
|
||||
async function ufwAdd() {
|
||||
const rule = document.getElementById('ufw-rule').value;
|
||||
const r = await apiPost('/api/security/firewall/add', {rule});
|
||||
showResult(r, 'ufw-status');
|
||||
}
|
||||
async function ufwDel() {
|
||||
const rule = document.getElementById('ufw-del-rule').value;
|
||||
const r = await apiPost('/api/security/firewall/delete', {rule});
|
||||
showResult(r, 'ufw-status');
|
||||
}
|
||||
async function ufwPreset(name) {
|
||||
if (!confirm('Apply ' + name + ' firewall preset?')) return;
|
||||
const r = await apiPost('/api/security/firewall/preset', {preset: name});
|
||||
showResult(r, 'ufw-status');
|
||||
}
|
||||
async function ufwDefault(policy, direction) {
|
||||
const r = await apiPost('/api/firewall/ufw/default', {policy, direction});
|
||||
showResult(r, 'ufw-defaults');
|
||||
}
|
||||
async function ufwAppList() {
|
||||
const r = await apiGet('/api/firewall/ufw/app-list');
|
||||
showResult(r, 'ufw-apps');
|
||||
}
|
||||
async function ufwLog() {
|
||||
const r = await apiGet('/api/firewall/ufw/log');
|
||||
showResult(r, 'ufw-log');
|
||||
}
|
||||
async function ufwLogLevel(level) {
|
||||
const r = await apiPost('/api/firewall/ufw/log-level', {level});
|
||||
showResult(r, 'ufw-log');
|
||||
}
|
||||
|
||||
// ── iptables ──
|
||||
async function iptList() {
|
||||
const r = await apiGet('/api/firewall/iptables/list');
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptListNat() {
|
||||
const r = await apiGet('/api/firewall/iptables/list-nat');
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptListMangle() {
|
||||
const r = await apiGet('/api/firewall/iptables/list-mangle');
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptCounters() {
|
||||
const r = await apiGet('/api/firewall/iptables/counters');
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptIp6() {
|
||||
const r = await apiGet('/api/firewall/iptables/ip6');
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptAdd() {
|
||||
const chain = document.getElementById('ipt-chain').value;
|
||||
const rule = document.getElementById('ipt-rule').value;
|
||||
const r = await apiPost('/api/firewall/iptables/add', {chain, rule});
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptInsert() {
|
||||
const chain = document.getElementById('ipt-chain').value;
|
||||
const rule = document.getElementById('ipt-rule').value;
|
||||
const pos = parseInt(document.getElementById('ipt-pos').value);
|
||||
const r = await apiPost('/api/firewall/iptables/insert', {chain, rule, position: pos});
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptDelete() {
|
||||
const chain = document.getElementById('ipt-del-chain').value;
|
||||
const rule_num = parseInt(document.getElementById('ipt-del-num').value);
|
||||
if (!confirm('Delete rule ' + rule_num + ' from ' + chain + '?')) return;
|
||||
const r = await apiPost('/api/firewall/iptables/delete', {chain, rule_num});
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptPolicy() {
|
||||
const chain = document.getElementById('ipt-pol-chain').value;
|
||||
const target = document.getElementById('ipt-pol-target').value;
|
||||
if (!confirm('Set ' + chain + ' policy to ' + target + '?')) return;
|
||||
const r = await apiPost('/api/firewall/iptables/policy', {chain, target});
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptBlockIP() {
|
||||
const ip = document.getElementById('ipt-ip').value;
|
||||
if (!ip) return;
|
||||
const r = await apiPost('/api/firewall/iptables/block-ip', {ip});
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptUnblockIP() {
|
||||
const ip = document.getElementById('ipt-ip').value;
|
||||
if (!ip) return;
|
||||
const r = await apiPost('/api/firewall/iptables/unblock-ip', {ip});
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptListBlocked() {
|
||||
const r = await apiGet('/api/firewall/iptables/blocked');
|
||||
showResult(r, 'ipt-rules');
|
||||
}
|
||||
async function iptSave() {
|
||||
const r = await apiPost('/api/firewall/iptables/save');
|
||||
showResult(r, 'ipt-persist');
|
||||
}
|
||||
async function iptRestore() {
|
||||
const r = await apiPost('/api/firewall/iptables/restore');
|
||||
showResult(r, 'ipt-persist');
|
||||
}
|
||||
async function iptFlush() {
|
||||
if (!confirm('Flush ALL iptables rules? This may lock you out if policy is DROP!')) return;
|
||||
const r = await apiPost('/api/firewall/iptables/flush');
|
||||
showResult(r, 'ipt-flush-out');
|
||||
}
|
||||
async function iptZero() {
|
||||
const r = await apiPost('/api/firewall/iptables/zero');
|
||||
showResult(r, 'ipt-flush-out');
|
||||
}
|
||||
async function iptLog() {
|
||||
const r = await apiGet('/api/firewall/iptables/log');
|
||||
showResult(r, 'ipt-log');
|
||||
}
|
||||
async function iptInstall() {
|
||||
const r = await apiPost('/api/firewall/iptables/install');
|
||||
showResult(r, 'ipt-install-out');
|
||||
}
|
||||
|
||||
// ── nftables ──
|
||||
async function nftList() {
|
||||
const r = await apiGet('/api/firewall/nftables/list');
|
||||
showResult(r, 'nft-rules');
|
||||
}
|
||||
async function nftTables() {
|
||||
const r = await apiGet('/api/firewall/nftables/tables');
|
||||
showResult(r, 'nft-rules');
|
||||
}
|
||||
async function nftCounters() {
|
||||
const r = await apiGet('/api/firewall/nftables/counters');
|
||||
showResult(r, 'nft-rules');
|
||||
}
|
||||
async function nftChains() {
|
||||
const table = document.getElementById('nft-table').value;
|
||||
const r = await apiPost('/api/firewall/nftables/chains', {table});
|
||||
showResult(r, 'nft-chains');
|
||||
}
|
||||
async function nftAddRule() {
|
||||
const table = document.getElementById('nft-add-table').value;
|
||||
const chain = document.getElementById('nft-add-chain').value;
|
||||
const rule = document.getElementById('nft-add-rule').value;
|
||||
const r = await apiPost('/api/firewall/nftables/add-rule', {table, chain, rule});
|
||||
showResult(r, 'nft-rules');
|
||||
}
|
||||
async function nftDelRule() {
|
||||
const table = document.getElementById('nft-del-table').value;
|
||||
const chain = document.getElementById('nft-del-chain').value;
|
||||
const handle = parseInt(document.getElementById('nft-del-handle').value);
|
||||
if (!confirm('Delete rule handle ' + handle + '?')) return;
|
||||
const r = await apiPost('/api/firewall/nftables/delete-rule', {table, chain, handle});
|
||||
showResult(r, 'nft-rules');
|
||||
}
|
||||
async function nftCreateTable() {
|
||||
const family = document.getElementById('nft-family').value;
|
||||
const name = document.getElementById('nft-new-table').value;
|
||||
const r = await apiPost('/api/firewall/nftables/create-table', {family, name});
|
||||
showResult(r, 'nft-rules');
|
||||
}
|
||||
async function nftCreateChain() {
|
||||
const table = document.getElementById('nft-family').value + ' ' + document.getElementById('nft-new-table').value;
|
||||
const chain = document.getElementById('nft-new-chain').value;
|
||||
const hook = document.getElementById('nft-hook').value;
|
||||
const r = await apiPost('/api/firewall/nftables/create-chain', {table, chain, hook});
|
||||
showResult(r, 'nft-rules');
|
||||
}
|
||||
async function nftSave() {
|
||||
const r = await apiPost('/api/firewall/nftables/save');
|
||||
showResult(r, 'nft-persist');
|
||||
}
|
||||
async function nftRestore() {
|
||||
const r = await apiPost('/api/firewall/nftables/restore');
|
||||
showResult(r, 'nft-persist');
|
||||
}
|
||||
async function nftConfig() {
|
||||
const r = await apiGet('/api/firewall/nftables/config');
|
||||
showResult(r, 'nft-persist');
|
||||
}
|
||||
async function nftFlush() {
|
||||
if (!confirm('Flush ALL nftables rules?')) return;
|
||||
const r = await apiPost('/api/firewall/nftables/flush');
|
||||
showResult(r, 'nft-flush-out');
|
||||
}
|
||||
async function nftInstall() {
|
||||
document.getElementById('nft-install-out').innerHTML = '<span class="info">Installing nftables...</span>';
|
||||
const r = await apiPost('/api/firewall/nftables/install');
|
||||
showResult(r, 'nft-install-out');
|
||||
}
|
||||
|
||||
// ── firewalld ──
|
||||
async function fwdStatus() {
|
||||
const r = await apiGet('/api/firewall/firewalld/status');
|
||||
showResult(r, 'fwd-status');
|
||||
}
|
||||
async function fwdReload() {
|
||||
const r = await apiPost('/api/firewall/firewalld/reload');
|
||||
showResult(r, 'fwd-status');
|
||||
}
|
||||
async function fwdPanicOn() {
|
||||
if (!confirm('Enable panic mode? ALL network traffic will be blocked!')) return;
|
||||
const r = await apiPost('/api/firewall/firewalld/panic-on');
|
||||
showResult(r, 'fwd-status');
|
||||
}
|
||||
async function fwdPanicOff() {
|
||||
const r = await apiPost('/api/firewall/firewalld/panic-off');
|
||||
showResult(r, 'fwd-status');
|
||||
}
|
||||
async function fwdZones() {
|
||||
const r = await apiGet('/api/firewall/firewalld/zones');
|
||||
showResult(r, 'fwd-zones');
|
||||
}
|
||||
async function fwdZoneInfo() {
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/zone-info', {zone});
|
||||
showResult(r, 'fwd-zones');
|
||||
}
|
||||
async function fwdSetDefault() {
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/default-zone', {zone});
|
||||
showResult(r, 'fwd-zones');
|
||||
}
|
||||
async function fwdServicesList() {
|
||||
const r = await apiGet('/api/firewall/firewalld/services-list');
|
||||
showResult(r, 'fwd-services');
|
||||
}
|
||||
async function fwdAddService() {
|
||||
const svc = document.getElementById('fwd-service').value;
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/add-service', {service: svc, zone});
|
||||
showResult(r, 'fwd-services');
|
||||
}
|
||||
async function fwdRemoveService() {
|
||||
const svc = document.getElementById('fwd-service').value;
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/remove-service', {service: svc, zone});
|
||||
showResult(r, 'fwd-services');
|
||||
}
|
||||
async function fwdAddPort() {
|
||||
const port = document.getElementById('fwd-port').value;
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/add-port', {port, zone});
|
||||
showResult(r, 'fwd-ports');
|
||||
}
|
||||
async function fwdRemovePort() {
|
||||
const port = document.getElementById('fwd-port').value;
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/remove-port', {port, zone});
|
||||
showResult(r, 'fwd-ports');
|
||||
}
|
||||
async function fwdAddRich() {
|
||||
const rule = document.getElementById('fwd-rich-rule').value;
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/add-rich-rule', {rule, zone});
|
||||
showResult(r, 'fwd-rich');
|
||||
}
|
||||
async function fwdRemoveRich() {
|
||||
const rule = document.getElementById('fwd-rich-rule').value;
|
||||
const zone = document.getElementById('fwd-zone').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/remove-rich-rule', {rule, zone});
|
||||
showResult(r, 'fwd-rich');
|
||||
}
|
||||
async function fwdBlockIP() {
|
||||
const ip = document.getElementById('fwd-ip').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/block-ip', {ip});
|
||||
showResult(r, 'fwd-block');
|
||||
}
|
||||
async function fwdUnblockIP() {
|
||||
const ip = document.getElementById('fwd-ip').value;
|
||||
const r = await apiPost('/api/firewall/firewalld/unblock-ip', {ip});
|
||||
showResult(r, 'fwd-block');
|
||||
}
|
||||
async function fwdLog() {
|
||||
const r = await apiGet('/api/firewall/firewalld/log');
|
||||
showResult(r, 'fwd-log');
|
||||
}
|
||||
async function fwdInstall() {
|
||||
document.getElementById('fwd-install-out').innerHTML = '<span class="info">Installing firewalld...</span>';
|
||||
const r = await apiPost('/api/firewall/firewalld/install');
|
||||
showResult(r, 'fwd-install-out');
|
||||
}
|
||||
|
||||
// ── CSF ──
|
||||
async function csfStatus() {
|
||||
const r = await apiGet('/api/firewall/csf/status');
|
||||
showResult(r, 'csf-status');
|
||||
}
|
||||
async function csfStart() {
|
||||
const r = await apiPost('/api/firewall/csf/start');
|
||||
showResult(r, 'csf-status');
|
||||
}
|
||||
async function csfStop() {
|
||||
if (!confirm('Stop CSF? This will flush all rules.')) return;
|
||||
const r = await apiPost('/api/firewall/csf/stop');
|
||||
showResult(r, 'csf-status');
|
||||
}
|
||||
async function csfRestart() {
|
||||
const r = await apiPost('/api/firewall/csf/restart');
|
||||
showResult(r, 'csf-status');
|
||||
}
|
||||
async function csfTest() {
|
||||
const r = await apiGet('/api/firewall/csf/test');
|
||||
showResult(r, 'csf-test');
|
||||
}
|
||||
async function csfList() {
|
||||
const r = await apiGet('/api/firewall/csf/list');
|
||||
showResult(r, 'csf-rules');
|
||||
}
|
||||
async function csfAllow() {
|
||||
const ip = document.getElementById('csf-ip').value;
|
||||
const comment = document.getElementById('csf-comment').value;
|
||||
const r = await apiPost('/api/firewall/csf/allow', {ip, comment});
|
||||
showResult(r, 'csf-ip-out');
|
||||
}
|
||||
async function csfDeny() {
|
||||
const ip = document.getElementById('csf-ip').value;
|
||||
const comment = document.getElementById('csf-comment').value;
|
||||
const r = await apiPost('/api/firewall/csf/deny', {ip, comment});
|
||||
showResult(r, 'csf-ip-out');
|
||||
}
|
||||
async function csfRemove() {
|
||||
const ip = document.getElementById('csf-ip').value;
|
||||
const r = await apiPost('/api/firewall/csf/remove', {ip});
|
||||
showResult(r, 'csf-ip-out');
|
||||
}
|
||||
async function csfGrep() {
|
||||
const ip = document.getElementById('csf-ip').value;
|
||||
const r = await apiPost('/api/firewall/csf/grep', {ip});
|
||||
showResult(r, 'csf-ip-out');
|
||||
}
|
||||
async function csfTempAllow() {
|
||||
const ip = document.getElementById('csf-ip').value;
|
||||
const ttl = parseInt(document.getElementById('csf-ttl').value);
|
||||
const r = await apiPost('/api/firewall/csf/temp-allow', {ip, ttl});
|
||||
showResult(r, 'csf-temp');
|
||||
}
|
||||
async function csfTempDeny() {
|
||||
const ip = document.getElementById('csf-ip').value;
|
||||
const ttl = parseInt(document.getElementById('csf-ttl').value);
|
||||
const r = await apiPost('/api/firewall/csf/temp-deny', {ip, ttl});
|
||||
showResult(r, 'csf-temp');
|
||||
}
|
||||
async function csfTempList() {
|
||||
const r = await apiGet('/api/firewall/csf/temp-list');
|
||||
showResult(r, 'csf-temp');
|
||||
}
|
||||
async function csfConfig() {
|
||||
const r = await apiGet('/api/firewall/csf/config');
|
||||
showResult(r, 'csf-config');
|
||||
}
|
||||
async function csfLog() {
|
||||
const r = await apiGet('/api/firewall/csf/log');
|
||||
showResult(r, 'csf-log');
|
||||
}
|
||||
async function csfInstall() {
|
||||
document.getElementById('csf-install-out').innerHTML = '<span class="info">Installing CSF...</span>';
|
||||
const r = await apiPost('/api/firewall/csf/install');
|
||||
showResult(r, 'csf-install-out');
|
||||
}
|
||||
|
||||
// ── Migration: UFW → iptables ──
|
||||
async function previewUfw2Ip() {
|
||||
const r = await apiGet('/api/security/firewall/status');
|
||||
showResult(r, 'm-ufw2ip-out');
|
||||
}
|
||||
async function runUfw2Ip() {
|
||||
if (!confirm('Migrate from UFW to raw iptables? UFW will be disabled. Make sure you have console access as backup!')) return;
|
||||
document.getElementById('m-ufw2ip-out').innerHTML = '<span class="info">Migrating UFW → iptables...</span>';
|
||||
const r = await apiPost('/api/firewall/migrate/ufw-to-iptables');
|
||||
showResult(r, 'm-ufw2ip-out');
|
||||
}
|
||||
|
||||
// ── Migration: iptables → UFW ──
|
||||
async function previewIp2Ufw() {
|
||||
const r = await apiGet('/api/firewall/iptables/list');
|
||||
showResult(r, 'm-ip2ufw-out');
|
||||
}
|
||||
async function runIp2Ufw() {
|
||||
if (!confirm('Migrate from iptables to UFW? Current rules will be converted. Make sure you have console access as backup!')) return;
|
||||
document.getElementById('m-ip2ufw-out').innerHTML = '<span class="info">Migrating iptables → UFW...</span>';
|
||||
const r = await apiPost('/api/firewall/migrate/iptables-to-ufw');
|
||||
showResult(r, 'm-ip2ufw-out');
|
||||
}
|
||||
|
||||
// Auto-load dashboard on page load
|
||||
fwDetect();
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user