feat(vhost-manager): Add centralized VHost manager
- Create secubox-app-vhost-manager package for unified vhost orchestration - Single CLI tool (secubox-vhost) manages HAProxy, DNS, Tor, Mesh, mitmproxy - Unified UCI config (/etc/config/vhosts) as single source of truth - Backend adapters for each component (haproxy.sh, dns.sh, tor.sh, mesh.sh, mitmproxy.sh) - Centralized backend resolution function (backends.sh) - Import tool for existing HAProxy vhosts - Validation of backend reachability before creation Also includes: - FAQ-TROUBLESHOOTING.md with LXC cgroup v1/v2 fixes - Fix mitmproxyctl cgroup v1 -> v2 syntax for container compatibility - HAProxy backend resolution bugfixes CLI commands: secubox-vhost add <domain> <service> <port> [--ssl] [--tor] [--mesh] secubox-vhost remove/list/status/enable/disable/set/sync/validate/import Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
0e0749ed08
commit
e13b6e4c8c
332
.claude/FAQ-TROUBLESHOOTING.md
Normal file
332
.claude/FAQ-TROUBLESHOOTING.md
Normal file
@ -0,0 +1,332 @@
|
||||
# SecuBox Troubleshooting FAQ
|
||||
|
||||
_Last updated: 2026-02-06_
|
||||
|
||||
This document collects resolved issues and their solutions for future reference.
|
||||
|
||||
---
|
||||
|
||||
## LXC Container Issues
|
||||
|
||||
### Issue: LXC containers fail to start with "Failed to mount /sys/fs/cgroup"
|
||||
|
||||
**Symptoms:**
|
||||
```
|
||||
ERROR cgfsng - Failed to create cgroup at_mnt 38()
|
||||
ERROR conf - Failed to mount "/sys/fs/cgroup"
|
||||
ERROR conf - Failed to setup remaining automatic mounts
|
||||
Received container state "ABORTING" instead of "RUNNING"
|
||||
```
|
||||
|
||||
**Root Cause:**
|
||||
OpenWrt uses cgroup v2 (unified hierarchy), but LXC configs may be using cgroup v1 syntax.
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. **Fix global LXC defaults** - Create/edit `/usr/share/lxc/config/common.conf`:
|
||||
```
|
||||
# Comment out all lxc.cgroup.devices lines (cgroup v1 syntax)
|
||||
# These cause "Failed to mount /sys/fs/cgroup" on cgroup v2 systems
|
||||
#lxc.cgroup.devices.deny = a
|
||||
#lxc.cgroup.devices.allow = c *:* m
|
||||
# ... (all device lines commented out)
|
||||
```
|
||||
|
||||
2. **Fix per-container config** - Replace cgroup v1 with v2 syntax:
|
||||
```
|
||||
# OLD (cgroup v1 - breaks on cgroup v2 systems):
|
||||
lxc.cgroup.memory.limit_in_bytes = 256M
|
||||
|
||||
# NEW (cgroup v2):
|
||||
lxc.cgroup2.memory.max = 268435456
|
||||
```
|
||||
|
||||
3. **Add cgroup v2 compatibility flags**:
|
||||
```
|
||||
lxc.seccomp.profile =
|
||||
lxc.tty.max = 0
|
||||
lxc.pty.max = 256
|
||||
lxc.cap.drop = sys_module mac_admin mac_override sys_time
|
||||
```
|
||||
|
||||
**Reference:** [OpenWrt Forum LXC Guide](https://forum.openwrt.org/t/openwrt-arm64-quick-lxc-howto-guide-lms-in-debian-system-in-lxc-container/99835)
|
||||
|
||||
---
|
||||
|
||||
### Issue: Alpine-based LXC rootfs incompatible with host cgroups
|
||||
|
||||
**Symptoms:**
|
||||
Container starts but immediately exits, or mounts fail inside container.
|
||||
|
||||
**Solution:**
|
||||
Use Debian-based rootfs instead of Alpine. Copy from a working container:
|
||||
```bash
|
||||
# Create new container from working Debian rootfs
|
||||
cp -a /srv/lxc/domoticz/rootfs /srv/lxc/newcontainer/rootfs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Networking Issues
|
||||
|
||||
### Issue: Port 80 requests redirected to port 8888
|
||||
|
||||
**Symptoms:**
|
||||
HTTP requests on port 80 go to mitmproxy (8888) instead of HAProxy.
|
||||
|
||||
**Root Cause:**
|
||||
mitmproxy WAN protection mode uses nftables to redirect incoming WAN traffic.
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check if mitmproxy WAN protection is enabled
|
||||
uci get mitmproxy.wan_protection.enabled
|
||||
|
||||
# Disable it
|
||||
uci set mitmproxy.wan_protection.enabled='0'
|
||||
uci commit mitmproxy
|
||||
|
||||
# Remove nftables rules
|
||||
nft delete table inet mitmproxy_wan
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: DNS rebind attack blocking internal IPs
|
||||
|
||||
**Symptoms:**
|
||||
BIND (or other DNS server) returns private IP (192.168.x.x), but clients get SERVFAIL.
|
||||
|
||||
**Root Cause:**
|
||||
dnsmasq has DNS rebind protection that blocks private IPs in DNS responses (security feature against DNS rebinding attacks).
|
||||
|
||||
**Solution:**
|
||||
Whitelist the domain in dnsmasq config:
|
||||
```
|
||||
# /etc/dnsmasq.d/yourdomain.conf
|
||||
rebind-domain-ok=/yourdomain.com/
|
||||
```
|
||||
|
||||
Then restart dnsmasq:
|
||||
```bash
|
||||
/etc/init.d/dnsmasq restart
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: WAN traffic not reaching Docker/LXC containers
|
||||
|
||||
**Symptoms:**
|
||||
External requests on ports 80/443 timeout, but LAN access works.
|
||||
|
||||
**Root Cause:**
|
||||
Firewall forward chain missing rules for WAN to Docker bridge.
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check firewall rules
|
||||
nft list chain inet fw4 forward_wan
|
||||
|
||||
# Add forward rules for HTTP/HTTPS
|
||||
# Via LuCI: Network > Firewall > Traffic Rules
|
||||
# Or via UCI:
|
||||
uci add firewall rule
|
||||
uci set firewall.@rule[-1].name='Forward-HAProxy-HTTP'
|
||||
uci set firewall.@rule[-1].src='wan'
|
||||
uci set firewall.@rule[-1].dest='docker'
|
||||
uci set firewall.@rule[-1].proto='tcp'
|
||||
uci set firewall.@rule[-1].dest_port='80'
|
||||
uci set firewall.@rule[-1].target='ACCEPT'
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall restart
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## HAProxy Issues
|
||||
|
||||
### Issue: HAProxy fails with "unable to find required use_backend"
|
||||
|
||||
**Symptoms:**
|
||||
```
|
||||
[ALERT] config : Proxy 'https-in': unable to find required use_backend: '127.0.0.1:8091'
|
||||
```
|
||||
|
||||
**Root Cause:**
|
||||
`haproxyctl generate` created invalid backend references using IP:port format instead of backend names.
|
||||
|
||||
**Solution:**
|
||||
1. Check for invalid backends:
|
||||
```bash
|
||||
grep -n 'use_backend.*127.0.0.1' /srv/haproxy/config/haproxy.cfg
|
||||
```
|
||||
|
||||
2. Fix by either:
|
||||
- Manually edit the config to use proper backend names
|
||||
- Delete the vhost config files and regenerate
|
||||
- Create missing backend definitions
|
||||
|
||||
```
|
||||
# Example fix - add missing backend definition:
|
||||
backend localai
|
||||
mode http
|
||||
server localai 127.0.0.1:8091 check inter 10s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Mitmproxy WAF Issues
|
||||
|
||||
### Issue: Mitmproxy container stops after haproxy-enable
|
||||
|
||||
**Symptoms:**
|
||||
`mitmproxyctl haproxy-enable` completes but container is STOPPED.
|
||||
|
||||
**Root Cause:**
|
||||
The enable command restarts services which regenerates the LXC config with cgroup v1 syntax.
|
||||
|
||||
**Solution:**
|
||||
Patch `/usr/sbin/mitmproxyctl` to use cgroup v2 syntax:
|
||||
```bash
|
||||
sed -i "s/lxc.cgroup.memory.limit_in_bytes/lxc.cgroup2.memory.max/" /usr/sbin/mitmproxyctl
|
||||
```
|
||||
|
||||
Also add seccomp disable after the cgroup line:
|
||||
```bash
|
||||
sed -i "/lxc.cgroup2.memory.max/a lxc.seccomp.profile =" /usr/sbin/mitmproxyctl
|
||||
```
|
||||
|
||||
Then manually fix the container config and restart:
|
||||
```bash
|
||||
# Edit /srv/lxc/mitmproxy/config with cgroup v2 syntax
|
||||
lxc-start -n mitmproxy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: Mitmproxy not detecting threats
|
||||
|
||||
**Symptoms:**
|
||||
`/srv/mitmproxy/threats.log` is empty or not being updated.
|
||||
|
||||
**Checklist:**
|
||||
1. Container running: `lxc-info -n mitmproxy`
|
||||
2. Port 8889 listening: `netstat -tlnp | grep 8889`
|
||||
3. HAProxy routing through mitmproxy: `grep mitmproxy_inspector /srv/haproxy/config/haproxy.cfg`
|
||||
4. Routes synced: `cat /srv/mitmproxy/haproxy-routes.json`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
mitmproxyctl sync-routes
|
||||
mitmproxyctl haproxy-enable
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DNS Provider Issues
|
||||
|
||||
### Issue: Let's Encrypt DNS-01 fails with CAA timeout
|
||||
|
||||
**Symptoms:**
|
||||
ACME challenge fails because CAA record lookup times out.
|
||||
|
||||
**Root Cause:**
|
||||
Router is authoritative for the domain but dnsmasq cannot serve CAA records.
|
||||
|
||||
**Solutions:**
|
||||
|
||||
1. **Remove local authority** - Let external DNS (Gandi/Cloudflare) handle everything:
|
||||
```
|
||||
# /etc/dnsmasq.d/yourdomain.conf
|
||||
# Remove: local=/yourdomain.com/
|
||||
# Keep only: server=/yourdomain.com/127.0.0.1#5353 (for BIND)
|
||||
# Or forward to external: server=/yourdomain.com/8.8.8.8
|
||||
```
|
||||
|
||||
2. **Use BIND instead of dnsmasq** for authoritative DNS (supports CAA records).
|
||||
|
||||
---
|
||||
|
||||
## Quick Diagnostic Commands
|
||||
|
||||
```bash
|
||||
# Check all LXC containers
|
||||
for d in /srv/lxc/*/; do n=$(basename "$d"); lxc-info -n "$n" 2>/dev/null | head -3; done
|
||||
|
||||
# Check listening ports
|
||||
netstat -tlnp | grep -E "80|443|8889|8089"
|
||||
|
||||
# Check firewall forward rules
|
||||
nft list chain inet fw4 forward_wan
|
||||
|
||||
# Check DNS resolution
|
||||
nslookup yourdomain.com 127.0.0.1
|
||||
|
||||
# Check mitmproxy status
|
||||
mitmproxyctl status
|
||||
|
||||
# Recent threats
|
||||
tail -20 /srv/mitmproxy/threats.log
|
||||
|
||||
# HAProxy config test
|
||||
haproxy -c -f /srv/haproxy/config/haproxy.cfg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Issue: haproxyctl generate creates invalid backend references
|
||||
|
||||
**Symptoms:**
|
||||
HAProxy config contains `use_backend 127.0.0.1:8091` instead of a named backend.
|
||||
|
||||
**Root Cause:**
|
||||
UCI vhost entries were created with `backend='127.0.0.1:8091'` (IP:port) instead of a named backend like `backend='localai'`.
|
||||
|
||||
This happens when:
|
||||
1. `haproxyctl vhost add` is used with a non-existent backend name
|
||||
2. Manual UCI edits use IP:port instead of backend name
|
||||
3. Scripts create vhosts without first creating the backend
|
||||
|
||||
**Solution:**
|
||||
1. Create the backend first:
|
||||
```bash
|
||||
haproxyctl backend add localai
|
||||
haproxyctl server add localai 127.0.0.1:8091
|
||||
```
|
||||
|
||||
2. Then fix the vhost to use the backend name:
|
||||
```bash
|
||||
uci set haproxy.<vhost_section>.backend='localai'
|
||||
uci set haproxy.<vhost_section>.original_backend='localai'
|
||||
uci commit haproxy
|
||||
haproxyctl generate
|
||||
```
|
||||
|
||||
3. Add missing backends to haproxy.cfg:
|
||||
```
|
||||
backend localai
|
||||
mode http
|
||||
server localai 127.0.0.1:8091 check inter 10s
|
||||
```
|
||||
|
||||
**Prevention:**
|
||||
Always create named backends before adding vhosts that reference them.
|
||||
|
||||
---
|
||||
|
||||
## Package-Specific Fixes Applied
|
||||
|
||||
| Package | Issue | Fix |
|
||||
|---------|-------|-----|
|
||||
| `mitmproxyctl` | cgroup v1 syntax | Changed to `lxc.cgroup2.memory.max` |
|
||||
| `dnsmasq` | DNS rebind blocking | Added `rebind-domain-ok` |
|
||||
| `haproxy` | Invalid backend names | Manual config repair |
|
||||
| LXC common.conf | cgroup v1 device rules | Commented out device lines |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OpenWrt LXC ARM64 Guide](https://forum.openwrt.org/t/openwrt-arm64-quick-lxc-howto-guide-lms-in-debian-system-in-lxc-container/99835)
|
||||
- [LXC cgroup v2 migration](https://linuxcontainers.org/lxc/manpages/man5/lxc.container.conf.5.html)
|
||||
- [dnsmasq man page - rebind-domain-ok](https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html)
|
||||
@ -327,3 +327,23 @@ _Last updated: 2026-02-06_
|
||||
- Service mirroring via reverse proxy chaining
|
||||
- Gossip-based exposure config sync
|
||||
- Submastering/multimixslaving architecture
|
||||
|
||||
32. **Threat Analyst KISS Dashboard v0.1.0 (2026-02-05)**
|
||||
- Regenerated `luci-app-threat-analyst` following CrowdSec dashboard KISS template pattern.
|
||||
- **Architectural changes**:
|
||||
- `api.js`: Migrated from plain object to `baseclass.extend()` pattern
|
||||
- `dashboard.css`: External CSS file (loaded dynamically in view)
|
||||
- `dashboard.js`: View-only JS following CrowdSec pattern with `view.extend()`
|
||||
- **CVE integration**:
|
||||
- System Health: New "CVE Alerts" indicator with warning icon (yellow) when CVEs detected
|
||||
- Threats table: New CVE column with hyperlinks to NVD (`https://nvd.nist.gov/vuln/detail/CVE-XXXX-XXXXX`)
|
||||
- CVE extraction: `extractCVE()` function in API parses CVE-YYYY-NNNNN patterns from scenarios
|
||||
- CVE row styling: Red-tinted background for CVE-related threats
|
||||
- **RPCD updates**:
|
||||
- Status method now returns `cve_alerts` count from CrowdSec alerts
|
||||
- Fixed output bug (grep `|| echo 0` causing double output)
|
||||
- **CSS additions**:
|
||||
- `.ta-health-icon.warning` for CVE alerts in health section
|
||||
- `.ta-cve-link` for NVD hyperlinks (red badge style)
|
||||
- `.ta-cve-row` for highlighted CVE threat rows
|
||||
- Following LuCI UI Generation Model Template v0.1.0 for future KISS modules.
|
||||
|
||||
@ -45,6 +45,15 @@ _Last updated: 2026-02-06_
|
||||
|
||||
_None currently active_
|
||||
|
||||
### Just Completed
|
||||
|
||||
- **Subdomain Generator Tool** — DONE (2026-02-05)
|
||||
- `secubox-subdomain` CLI for generative subdomain management
|
||||
- Automates: DNS A record + HAProxy vhost + UCI registration
|
||||
- Uses wildcard certificate (*.zone) for instant SSL
|
||||
- Quick-add shortcuts for common services (gitea, grafana, jellyfin, etc.)
|
||||
- Part of Punk Exposure infrastructure
|
||||
|
||||
### Next Up — Couche 1
|
||||
|
||||
1. **Guacamole Pre-built Binaries**
|
||||
@ -89,6 +98,13 @@ _None currently active_
|
||||
- Created `luci-app-threat-analyst` with AI chatbot dashboard
|
||||
- RPCD handler with 10 methods for status, chat, rules, approval
|
||||
|
||||
- **Threat Analyst KISS Dashboard v0.1.0** — DONE (2026-02-05)
|
||||
- Regenerated LuCI dashboard following CrowdSec KISS template pattern
|
||||
- External CSS loading, baseclass.extend() API pattern
|
||||
- CVE alerts in System Health section
|
||||
- CVE column in threats table with NVD hyperlinks
|
||||
- AI Security Assistant chat interface
|
||||
|
||||
- **MCP Server Implementation** — DONE (2026-02-06)
|
||||
- Created `secubox-mcp-server` package with JSON-RPC 2.0 over stdio
|
||||
- 9 core tools: crowdsec.alerts/decisions, waf.logs, dns.queries, network.flows, system.metrics, wireguard.status, uci.get/set
|
||||
|
||||
@ -278,7 +278,8 @@
|
||||
"Bash(jsonfilter:*)",
|
||||
"WebFetch(domain:zigbeefordomoticz.github.io)",
|
||||
"WebFetch(domain:rustdesk.com)",
|
||||
"WebFetch(domain:deepwiki.com)"
|
||||
"WebFetch(domain:deepwiki.com)",
|
||||
"Bash(traceroute:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,25 +54,35 @@ method_status() {
|
||||
stats_port=$(get_uci main stats_port 8404)
|
||||
stats_enabled=$(get_uci main stats_enabled 1)
|
||||
|
||||
# Check container status - prefer lxc-info, fallback to pgrep lxc-start
|
||||
if command -v lxc-info >/dev/null 2>&1; then
|
||||
container_running=$(lxc-info -n haproxy -s 2>/dev/null | grep -q "RUNNING" && echo "1" || echo "0")
|
||||
else
|
||||
# Fallback: check if lxc-start is running for haproxy
|
||||
container_running=$(pgrep -f "lxc-start.*-n haproxy" >/dev/null 2>&1 && echo "1" || echo "0")
|
||||
# Check container status - Docker first, then LXC
|
||||
container_running="0"
|
||||
haproxy_running="0"
|
||||
|
||||
# Check Docker container (secubox-haproxy or haproxy)
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
if docker ps --format '{{.Names}}' 2>/dev/null | grep -qE '^(secubox-haproxy|haproxy)$'; then
|
||||
container_running="1"
|
||||
haproxy_running="1"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check HAProxy process
|
||||
if [ "$container_running" = "1" ]; then
|
||||
# Try lxc-attach first, fallback to direct pgrep
|
||||
if command -v lxc-attach >/dev/null 2>&1; then
|
||||
haproxy_running=$(lxc-attach -n haproxy -- pgrep haproxy >/dev/null 2>&1 && echo "1" || echo "0")
|
||||
else
|
||||
# Fallback: check if haproxy process exists (it runs in container but visible from host)
|
||||
haproxy_running=$(pgrep -f "haproxy.*haproxy.cfg" >/dev/null 2>&1 && echo "1" || echo "0")
|
||||
# If not Docker, check LXC
|
||||
if [ "$container_running" = "0" ]; then
|
||||
if command -v lxc-info >/dev/null 2>&1; then
|
||||
if lxc-info -n haproxy -s 2>/dev/null | grep -q "RUNNING"; then
|
||||
container_running="1"
|
||||
# Check HAProxy process inside LXC
|
||||
haproxy_running=$(lxc-attach -n haproxy -- pgrep haproxy >/dev/null 2>&1 && echo "1" || echo "0")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Final fallback: check if HAProxy port is listening
|
||||
if [ "$container_running" = "0" ]; then
|
||||
if netstat -tln 2>/dev/null | grep -q ":80 "; then
|
||||
container_running="1"
|
||||
haproxy_running="1"
|
||||
fi
|
||||
else
|
||||
haproxy_running="0"
|
||||
fi
|
||||
|
||||
json_init
|
||||
|
||||
@ -28,6 +28,7 @@ define Package/luci-app-threat-analyst/install
|
||||
|
||||
$(INSTALL_DIR) $(1)/www/luci-static/resources/threat-analyst
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/threat-analyst/api.js $(1)/www/luci-static/resources/threat-analyst/
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/threat-analyst/dashboard.css $(1)/www/luci-static/resources/threat-analyst/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,luci-app-threat-analyst))
|
||||
|
||||
@ -1,6 +1,19 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require rpc';
|
||||
|
||||
/**
|
||||
* Threat Analyst API
|
||||
* Package: luci-app-threat-analyst
|
||||
* RPCD object: luci.threat-analyst
|
||||
* Version: 0.1.0
|
||||
*
|
||||
* Generative AI-powered threat filtering for:
|
||||
* - CrowdSec autoban scenarios
|
||||
* - mitmproxy filter rules
|
||||
* - WAF rules
|
||||
*/
|
||||
|
||||
var callStatus = rpc.declare({
|
||||
object: 'luci.threat-analyst',
|
||||
method: 'status',
|
||||
@ -14,13 +27,6 @@ var callGetThreats = rpc.declare({
|
||||
expect: { }
|
||||
});
|
||||
|
||||
var callGetAlerts = rpc.declare({
|
||||
object: 'luci.threat-analyst',
|
||||
method: 'get_alerts',
|
||||
params: ['limit'],
|
||||
expect: { }
|
||||
});
|
||||
|
||||
var callGetPending = rpc.declare({
|
||||
object: 'luci.threat-analyst',
|
||||
method: 'get_pending',
|
||||
@ -34,12 +40,6 @@ var callChat = rpc.declare({
|
||||
expect: { }
|
||||
});
|
||||
|
||||
var callAnalyze = rpc.declare({
|
||||
object: 'luci.threat-analyst',
|
||||
method: 'analyze',
|
||||
expect: { }
|
||||
});
|
||||
|
||||
var callGenerateRules = rpc.declare({
|
||||
object: 'luci.threat-analyst',
|
||||
method: 'generate_rules',
|
||||
@ -67,15 +67,72 @@ var callRunCycle = rpc.declare({
|
||||
expect: { }
|
||||
});
|
||||
|
||||
return {
|
||||
status: callStatus,
|
||||
function formatRelativeTime(dateStr) {
|
||||
if (!dateStr) return 'N/A';
|
||||
try {
|
||||
var date = new Date(dateStr);
|
||||
var now = new Date();
|
||||
var seconds = Math.floor((now - date) / 1000);
|
||||
if (seconds < 60) return seconds + 's ago';
|
||||
if (seconds < 3600) return Math.floor(seconds / 60) + 'm ago';
|
||||
if (seconds < 86400) return Math.floor(seconds / 3600) + 'h ago';
|
||||
return Math.floor(seconds / 86400) + 'd ago';
|
||||
} catch(e) {
|
||||
return dateStr;
|
||||
}
|
||||
}
|
||||
|
||||
function parseScenario(scenario) {
|
||||
if (!scenario) return 'Unknown';
|
||||
var parts = scenario.split('/');
|
||||
var name = parts[parts.length - 1];
|
||||
return name.split('-').map(function(word) {
|
||||
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||
}).join(' ');
|
||||
}
|
||||
|
||||
function getSeverityClass(scenario) {
|
||||
if (!scenario) return 'medium';
|
||||
var s = scenario.toLowerCase();
|
||||
if (s.includes('malware') || s.includes('exploit') || s.includes('cve')) return 'critical';
|
||||
if (s.includes('bruteforce') || s.includes('scan')) return 'high';
|
||||
if (s.includes('crawl') || s.includes('http')) return 'low';
|
||||
return 'medium';
|
||||
}
|
||||
|
||||
function extractCVE(scenario) {
|
||||
if (!scenario) return null;
|
||||
// Match CVE patterns: CVE-YYYY-NNNNN
|
||||
var match = scenario.match(/CVE-\d{4}-\d{4,}/i);
|
||||
return match ? match[0].toUpperCase() : null;
|
||||
}
|
||||
|
||||
return baseclass.extend({
|
||||
getStatus: callStatus,
|
||||
getThreats: callGetThreats,
|
||||
getAlerts: callGetAlerts,
|
||||
getPending: callGetPending,
|
||||
chat: callChat,
|
||||
analyze: callAnalyze,
|
||||
generateRules: callGenerateRules,
|
||||
approveRule: callApproveRule,
|
||||
rejectRule: callRejectRule,
|
||||
runCycle: callRunCycle
|
||||
};
|
||||
runCycle: callRunCycle,
|
||||
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
parseScenario: parseScenario,
|
||||
getSeverityClass: getSeverityClass,
|
||||
extractCVE: extractCVE,
|
||||
|
||||
getOverview: function() {
|
||||
return Promise.all([
|
||||
callStatus(),
|
||||
callGetThreats(20),
|
||||
callGetPending()
|
||||
]).then(function(results) {
|
||||
return {
|
||||
status: results[0] || {},
|
||||
threats: (results[1] || {}).threats || [],
|
||||
pending: (results[2] || {}).pending || []
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -0,0 +1,454 @@
|
||||
/* Threat Analyst Dashboard CSS - v0.1.0 */
|
||||
/* Following CrowdSec Dashboard KISS pattern */
|
||||
|
||||
.ta-view {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.ta-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid var(--border-color-medium, #ddd);
|
||||
}
|
||||
|
||||
.ta-title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: var(--text-color, #333);
|
||||
}
|
||||
|
||||
.ta-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ta-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.ta-dot.online { background: #4caf50; }
|
||||
.ta-dot.offline { background: #f44336; }
|
||||
|
||||
/* Navigation */
|
||||
.ta-nav {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-bottom: 20px;
|
||||
background: var(--background-color-alt, #f5f5f5);
|
||||
padding: 4px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.ta-nav a {
|
||||
padding: 8px 16px;
|
||||
border-radius: 6px;
|
||||
text-decoration: none;
|
||||
color: var(--text-color, #333);
|
||||
font-size: 14px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.ta-nav a:hover {
|
||||
background: var(--background-color, #fff);
|
||||
}
|
||||
|
||||
.ta-nav a.active {
|
||||
background: var(--primary-color, #2196f3);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Stats */
|
||||
.ta-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.ta-stat {
|
||||
background: var(--background-color, #fff);
|
||||
border: 1px solid var(--border-color-low, #eee);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ta-stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: var(--primary-color, #2196f3);
|
||||
}
|
||||
|
||||
.ta-stat-label {
|
||||
font-size: 12px;
|
||||
color: var(--text-color-secondary, #666);
|
||||
margin-top: 4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.ta-stat.success .ta-stat-value { color: #4caf50; }
|
||||
.ta-stat.warning .ta-stat-value { color: #ff9800; }
|
||||
.ta-stat.danger .ta-stat-value { color: #f44336; }
|
||||
|
||||
/* Grid Layout */
|
||||
.ta-grid-2 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.ta-grid-2 { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.ta-card {
|
||||
background: var(--background-color, #fff);
|
||||
border: 1px solid var(--border-color-low, #eee);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ta-card-header {
|
||||
padding: 12px 16px;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
background: var(--background-color-alt, #f9f9f9);
|
||||
border-bottom: 1px solid var(--border-color-low, #eee);
|
||||
}
|
||||
|
||||
.ta-card-body {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.ta-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.ta-table th,
|
||||
.ta-table td {
|
||||
padding: 10px 12px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color-low, #eee);
|
||||
}
|
||||
|
||||
.ta-table th {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-color-secondary, #666);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ta-table tbody tr:hover {
|
||||
background: var(--background-color-alt, #f9f9f9);
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
.ta-badge {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ta-badge.critical { background: #f44336; color: white; }
|
||||
.ta-badge.high { background: #ff9800; color: white; }
|
||||
.ta-badge.medium { background: #ffc107; color: #333; }
|
||||
.ta-badge.low { background: #4caf50; color: white; }
|
||||
|
||||
.ta-badge.crowdsec { background: #5c6bc0; color: white; }
|
||||
.ta-badge.mitmproxy { background: #26a69a; color: white; }
|
||||
.ta-badge.waf { background: #7e57c2; color: white; }
|
||||
|
||||
/* Buttons */
|
||||
.ta-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.ta-btn:hover { opacity: 0.9; }
|
||||
|
||||
.ta-btn-primary { background: var(--primary-color, #2196f3); color: white; }
|
||||
.ta-btn-success { background: #4caf50; color: white; }
|
||||
.ta-btn-warning { background: #ff9800; color: white; }
|
||||
.ta-btn-danger { background: #f44336; color: white; }
|
||||
.ta-btn-sm { padding: 4px 10px; font-size: 12px; }
|
||||
|
||||
/* Actions Bar */
|
||||
.ta-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* Pending Rules */
|
||||
.ta-pending-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ta-pending-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
background: var(--background-color-alt, #f9f9f9);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.ta-pending-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.ta-pending-type {
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.ta-pending-date {
|
||||
font-size: 12px;
|
||||
color: var(--text-color-secondary, #666);
|
||||
}
|
||||
|
||||
.ta-pending-actions {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
/* Chat */
|
||||
.ta-chat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.ta-chat-messages {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
background: var(--background-color-alt, #f5f5f5);
|
||||
border-radius: 6px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.ta-message {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ta-message.user {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.ta-message-bubble {
|
||||
max-width: 80%;
|
||||
padding: 10px 14px;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.ta-message.user .ta-message-bubble {
|
||||
background: var(--primary-color, #2196f3);
|
||||
color: white;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.ta-message.ai .ta-message-bubble {
|
||||
background: var(--background-color, #fff);
|
||||
border: 1px solid var(--border-color-low, #eee);
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.ta-message-time {
|
||||
font-size: 10px;
|
||||
color: var(--text-color-secondary, #999);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.ta-chat-input {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ta-chat-input input {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--border-color-medium, #ddd);
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ta-chat-input input:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color, #2196f3);
|
||||
}
|
||||
|
||||
/* Empty State */
|
||||
.ta-empty {
|
||||
text-align: center;
|
||||
padding: 24px;
|
||||
color: var(--text-color-secondary, #666);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* IP display */
|
||||
.ta-ip {
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Scenario display */
|
||||
.ta-scenario {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* Time display */
|
||||
.ta-time {
|
||||
font-size: 12px;
|
||||
color: var(--text-color-secondary, #666);
|
||||
}
|
||||
|
||||
/* Health Grid */
|
||||
.ta-health {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ta-health-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 10px;
|
||||
background: var(--background-color-alt, #f9f9f9);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.ta-health-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ta-health-icon.ok {
|
||||
background: #e8f5e9;
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.ta-health-icon.error {
|
||||
background: #ffebee;
|
||||
color: #f44336;
|
||||
}
|
||||
|
||||
.ta-health-icon.warning {
|
||||
background: #fff3e0;
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.ta-health-label {
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.ta-health-value {
|
||||
font-size: 12px;
|
||||
color: var(--text-color-secondary, #666);
|
||||
}
|
||||
|
||||
/* Targets Grid */
|
||||
.ta-targets {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ta-target {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
background: var(--background-color-alt, #f9f9f9);
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.ta-target:hover {
|
||||
border-color: var(--primary-color, #2196f3);
|
||||
}
|
||||
|
||||
.ta-target-icon {
|
||||
font-size: 24px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ta-target-name {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ta-target-desc {
|
||||
font-size: 11px;
|
||||
color: var(--text-color-secondary, #666);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
/* CVE Styles */
|
||||
.ta-cve-link {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
background: #ffebee;
|
||||
color: #c62828;
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
font-family: monospace;
|
||||
text-decoration: none;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.ta-cve-link:hover {
|
||||
background: #ef9a9a;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ta-no-cve {
|
||||
color: var(--text-color-secondary, #999);
|
||||
}
|
||||
|
||||
.ta-cve-row {
|
||||
background: rgba(244, 67, 54, 0.05);
|
||||
}
|
||||
|
||||
.ta-cve-row:hover {
|
||||
background: rgba(244, 67, 54, 0.1) !important;
|
||||
}
|
||||
@ -3,188 +3,241 @@
|
||||
'require dom';
|
||||
'require poll';
|
||||
'require ui';
|
||||
'require threat-analyst/api as api';
|
||||
'require threat-analyst.api as api';
|
||||
|
||||
/**
|
||||
* Threat Analyst Dashboard - v0.1.0
|
||||
* Generative AI-powered threat filtering
|
||||
*
|
||||
* Following CrowdSec Dashboard KISS template pattern
|
||||
*/
|
||||
|
||||
return view.extend({
|
||||
chatHistory: [],
|
||||
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
api.status(),
|
||||
api.getThreats(20),
|
||||
api.getPending()
|
||||
]);
|
||||
var link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = L.resource('threat-analyst/dashboard.css');
|
||||
document.head.appendChild(link);
|
||||
return api.getOverview().catch(function() { return {}; });
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
var status = data[0] || {};
|
||||
var threats = (data[1] || {}).threats || [];
|
||||
var pending = (data[2] || {}).pending || [];
|
||||
var self = this;
|
||||
var s = data.status || {};
|
||||
var threats = data.threats || [];
|
||||
var pending = data.pending || [];
|
||||
|
||||
// Add CSS
|
||||
var style = E('style', {}, `
|
||||
.ta-dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
|
||||
.ta-card { background: var(--bg-alt, #f8f9fa); border-radius: 8px; padding: 16px; }
|
||||
.ta-card h3 { margin: 0 0 12px 0; font-size: 14px; text-transform: uppercase; opacity: 0.7; }
|
||||
.ta-status-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
|
||||
.ta-stat { text-align: center; padding: 12px; background: var(--bg, #fff); border-radius: 6px; }
|
||||
.ta-stat-value { font-size: 24px; font-weight: bold; color: var(--primary, #2196f3); }
|
||||
.ta-stat-label { font-size: 11px; opacity: 0.6; margin-top: 4px; }
|
||||
.ta-stat.warning .ta-stat-value { color: #ff9800; }
|
||||
.ta-stat.danger .ta-stat-value { color: #f44336; }
|
||||
.ta-stat.success .ta-stat-value { color: #4caf50; }
|
||||
|
||||
.ta-chat { grid-column: span 2; }
|
||||
.ta-chat-messages { height: 300px; overflow-y: auto; background: var(--bg, #fff); border-radius: 6px; padding: 12px; margin-bottom: 12px; }
|
||||
.ta-message { margin-bottom: 12px; }
|
||||
.ta-message.user { text-align: right; }
|
||||
.ta-message-bubble { display: inline-block; max-width: 80%; padding: 8px 12px; border-radius: 12px; }
|
||||
.ta-message.user .ta-message-bubble { background: #2196f3; color: white; }
|
||||
.ta-message.ai .ta-message-bubble { background: var(--bg-alt, #e3e3e3); }
|
||||
.ta-message-time { font-size: 10px; opacity: 0.5; margin-top: 4px; }
|
||||
.ta-chat-input { display: flex; gap: 8px; }
|
||||
.ta-chat-input input { flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 6px; }
|
||||
.ta-chat-input button { padding: 10px 20px; background: #2196f3; color: white; border: none; border-radius: 6px; cursor: pointer; }
|
||||
|
||||
.ta-threats { grid-column: span 2; }
|
||||
.ta-threats-table { width: 100%; border-collapse: collapse; }
|
||||
.ta-threats-table th, .ta-threats-table td { padding: 8px; text-align: left; border-bottom: 1px solid #eee; }
|
||||
.ta-threats-table th { font-size: 11px; text-transform: uppercase; opacity: 0.6; }
|
||||
.ta-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; }
|
||||
.ta-badge.critical { background: #f44336; color: white; }
|
||||
.ta-badge.high { background: #ff9800; color: white; }
|
||||
.ta-badge.medium { background: #ffc107; color: black; }
|
||||
.ta-badge.low { background: #4caf50; color: white; }
|
||||
|
||||
.ta-actions { display: flex; gap: 8px; margin-top: 16px; }
|
||||
.ta-btn { padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
||||
.ta-btn-primary { background: #2196f3; color: white; }
|
||||
.ta-btn-success { background: #4caf50; color: white; }
|
||||
.ta-btn-warning { background: #ff9800; color: white; }
|
||||
|
||||
.ta-pending { margin-top: 20px; }
|
||||
.ta-pending-item { display: flex; justify-content: space-between; align-items: center; padding: 10px; background: var(--bg, #fff); border-radius: 6px; margin-bottom: 8px; }
|
||||
`);
|
||||
|
||||
var statusCard = E('div', { 'class': 'ta-card' }, [
|
||||
E('h3', {}, 'Agent Status'),
|
||||
E('div', { 'class': 'ta-status-grid' }, [
|
||||
E('div', { 'class': 'ta-stat ' + (status.daemon_running ? 'success' : 'warning') }, [
|
||||
E('div', { 'class': 'ta-stat-value' }, status.daemon_running ? 'ON' : 'OFF'),
|
||||
E('div', { 'class': 'ta-stat-label' }, 'Daemon')
|
||||
]),
|
||||
E('div', { 'class': 'ta-stat ' + (status.localai_status === 'online' ? 'success' : 'danger') }, [
|
||||
E('div', { 'class': 'ta-stat-value' }, status.localai_status === 'online' ? 'OK' : 'OFF'),
|
||||
E('div', { 'class': 'ta-stat-label' }, 'LocalAI')
|
||||
]),
|
||||
E('div', { 'class': 'ta-stat ' + (status.recent_threats > 10 ? 'danger' : status.recent_threats > 0 ? 'warning' : 'success') }, [
|
||||
E('div', { 'class': 'ta-stat-value' }, status.recent_threats || 0),
|
||||
E('div', { 'class': 'ta-stat-label' }, 'Threats (1h)')
|
||||
var view = E('div', { 'class': 'ta-view' }, [
|
||||
// Header
|
||||
E('div', { 'class': 'ta-header' }, [
|
||||
E('div', { 'class': 'ta-title' }, 'Threat Analyst'),
|
||||
E('div', { 'class': 'ta-status' }, [
|
||||
E('span', { 'class': 'ta-dot ' + (s.daemon_running ? 'online' : 'offline') }),
|
||||
s.daemon_running ? 'Running' : 'Stopped'
|
||||
])
|
||||
]),
|
||||
|
||||
// Stats
|
||||
E('div', { 'class': 'ta-stats', 'id': 'ta-stats' }, this.renderStats(s, pending)),
|
||||
|
||||
// Two column layout
|
||||
E('div', { 'class': 'ta-grid-2' }, [
|
||||
// Health card
|
||||
E('div', { 'class': 'ta-card' }, [
|
||||
E('div', { 'class': 'ta-card-header' }, 'System Health'),
|
||||
E('div', { 'class': 'ta-card-body' }, this.renderHealth(s))
|
||||
]),
|
||||
// Pending Rules card
|
||||
E('div', { 'class': 'ta-card' }, [
|
||||
E('div', { 'class': 'ta-card-header' }, 'Pending Rules (' + pending.length + ')'),
|
||||
E('div', { 'class': 'ta-card-body', 'id': 'ta-pending' }, this.renderPending(pending))
|
||||
])
|
||||
]),
|
||||
|
||||
// Generate Rules card
|
||||
E('div', { 'class': 'ta-card' }, [
|
||||
E('div', { 'class': 'ta-card-header' }, 'Generate Filter Rules'),
|
||||
E('div', { 'class': 'ta-card-body' }, this.renderTargets())
|
||||
]),
|
||||
|
||||
// Threats card
|
||||
E('div', { 'class': 'ta-card' }, [
|
||||
E('div', { 'class': 'ta-card-header' }, 'Recent Threats from CrowdSec'),
|
||||
E('div', { 'class': 'ta-card-body', 'id': 'ta-threats' }, this.renderThreats(threats))
|
||||
]),
|
||||
|
||||
// AI Chat card
|
||||
E('div', { 'class': 'ta-card' }, [
|
||||
E('div', { 'class': 'ta-card-header' }, 'AI Security Assistant'),
|
||||
E('div', { 'class': 'ta-card-body' }, this.renderChat())
|
||||
])
|
||||
]);
|
||||
|
||||
poll.add(L.bind(this.pollData, this), 30);
|
||||
return view;
|
||||
},
|
||||
|
||||
renderStats: function(s, pending) {
|
||||
var stats = [
|
||||
{ label: 'Daemon', value: s.daemon_running ? 'ON' : 'OFF', type: s.daemon_running ? 'success' : 'danger' },
|
||||
{ label: 'LocalAI', value: s.localai_status === 'online' ? 'OK' : 'OFF', type: s.localai_status === 'online' ? 'success' : 'danger' },
|
||||
{ label: 'Threats (1h)', value: s.recent_threats || 0, type: (s.recent_threats || 0) > 10 ? 'danger' : (s.recent_threats || 0) > 0 ? 'warning' : 'success' },
|
||||
{ label: 'Pending', value: pending.length || 0, type: (pending.length || 0) > 0 ? 'warning' : '' }
|
||||
];
|
||||
return stats.map(function(st) {
|
||||
return E('div', { 'class': 'ta-stat ' + st.type }, [
|
||||
E('div', { 'class': 'ta-stat-value' }, String(st.value)),
|
||||
E('div', { 'class': 'ta-stat-label' }, st.label)
|
||||
]);
|
||||
});
|
||||
},
|
||||
|
||||
renderHealth: function(s) {
|
||||
var cveCount = s.cve_alerts || 0;
|
||||
var checks = [
|
||||
{ label: 'Daemon', ok: s.daemon_running },
|
||||
{ label: 'LocalAI', ok: s.localai_status === 'online' },
|
||||
{ label: 'CrowdSec', ok: s.recent_threats !== undefined },
|
||||
{ label: 'CVE Alerts', ok: cveCount === 0, value: cveCount > 0 ? cveCount + ' Active' : 'None', warn: cveCount > 0 },
|
||||
{ label: 'Auto-Apply', ok: s.enabled, value: s.enabled ? 'Enabled' : 'Manual' }
|
||||
];
|
||||
return E('div', { 'class': 'ta-health' }, checks.map(function(c) {
|
||||
var valueText = c.value ? c.value : (c.ok ? 'OK' : 'Unavailable');
|
||||
var iconClass = c.warn ? 'warning' : (c.ok ? 'ok' : 'error');
|
||||
var iconChar = c.warn ? '\u26A0' : (c.ok ? '\u2713' : '\u2717');
|
||||
return E('div', { 'class': 'ta-health-item' }, [
|
||||
E('div', { 'class': 'ta-health-icon ' + iconClass }, iconChar),
|
||||
E('div', {}, [
|
||||
E('div', { 'class': 'ta-health-label' }, c.label),
|
||||
E('div', { 'class': 'ta-health-value' }, valueText)
|
||||
])
|
||||
]);
|
||||
}));
|
||||
},
|
||||
|
||||
renderPending: function(pending) {
|
||||
var self = this;
|
||||
if (!pending.length) {
|
||||
return E('div', { 'class': 'ta-empty' }, 'No pending rules for approval');
|
||||
}
|
||||
return E('div', { 'class': 'ta-pending-list' }, pending.map(function(rule) {
|
||||
return E('div', { 'class': 'ta-pending-item' }, [
|
||||
E('div', { 'class': 'ta-pending-info' }, [
|
||||
E('div', { 'class': 'ta-pending-type' }, [
|
||||
E('span', { 'class': 'ta-badge ' + rule.type }, rule.type)
|
||||
]),
|
||||
E('div', { 'class': 'ta-pending-date' }, (rule.created || '').substring(0, 10))
|
||||
]),
|
||||
E('div', { 'class': 'ta-pending-actions' }, [
|
||||
E('button', {
|
||||
'class': 'ta-btn ta-btn-success ta-btn-sm',
|
||||
'click': function() { self.approveRule(rule.id); }
|
||||
}, 'Approve'),
|
||||
E('button', {
|
||||
'class': 'ta-btn ta-btn-danger ta-btn-sm',
|
||||
'click': function() { self.rejectRule(rule.id); }
|
||||
}, 'Reject')
|
||||
])
|
||||
]);
|
||||
}));
|
||||
},
|
||||
|
||||
renderTargets: function() {
|
||||
var self = this;
|
||||
var targets = [
|
||||
{ id: 'crowdsec', name: 'CrowdSec', desc: 'Generate autoban scenarios', icon: '\uD83D\uDEE1' },
|
||||
{ id: 'mitmproxy', name: 'mitmproxy', desc: 'Generate Python filters', icon: '\uD83D\uDD0D' },
|
||||
{ id: 'waf', name: 'WAF', desc: 'Generate ModSecurity rules', icon: '\uD83D\uDEA7' }
|
||||
];
|
||||
return E('div', {}, [
|
||||
E('div', { 'class': 'ta-targets' }, targets.map(function(t) {
|
||||
return E('div', {
|
||||
'class': 'ta-target',
|
||||
'click': function() { self.generateRules(t.id); }
|
||||
}, [
|
||||
E('div', { 'class': 'ta-target-icon' }, t.icon),
|
||||
E('div', { 'class': 'ta-target-name' }, t.name),
|
||||
E('div', { 'class': 'ta-target-desc' }, t.desc)
|
||||
]);
|
||||
})),
|
||||
E('div', { 'class': 'ta-actions' }, [
|
||||
E('button', {
|
||||
'class': 'ta-btn ta-btn-primary',
|
||||
'click': function() { self.runCycle(); }
|
||||
}, 'Run Analysis'),
|
||||
'click': function() { self.runAnalysis(); }
|
||||
}, 'Run Analysis Cycle'),
|
||||
E('button', {
|
||||
'class': 'ta-btn ta-btn-success',
|
||||
'click': function() { self.generateRules('all'); }
|
||||
}, 'Generate Rules')
|
||||
}, 'Generate All Rules')
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
var pendingCard = E('div', { 'class': 'ta-card' }, [
|
||||
E('h3', {}, 'Pending Rules (' + pending.length + ')'),
|
||||
E('div', { 'class': 'ta-pending', 'id': 'pending-rules' },
|
||||
pending.length === 0 ? E('em', {}, 'No pending rules') :
|
||||
pending.map(function(rule) {
|
||||
return E('div', { 'class': 'ta-pending-item' }, [
|
||||
E('span', {}, rule.type + ' - ' + (rule.created || '').substring(0, 10)),
|
||||
E('div', {}, [
|
||||
E('button', {
|
||||
'class': 'ta-btn ta-btn-success',
|
||||
'style': 'padding: 4px 8px; margin-right: 4px;',
|
||||
'click': function() { self.approveRule(rule.id); }
|
||||
}, 'Approve'),
|
||||
E('button', {
|
||||
'class': 'ta-btn ta-btn-warning',
|
||||
'style': 'padding: 4px 8px;',
|
||||
'click': function() { self.rejectRule(rule.id); }
|
||||
}, 'Reject')
|
||||
])
|
||||
]);
|
||||
})
|
||||
)
|
||||
renderThreats: function(threats) {
|
||||
if (!threats.length) {
|
||||
return E('div', { 'class': 'ta-empty' }, 'No recent threats detected');
|
||||
}
|
||||
return E('table', { 'class': 'ta-table' }, [
|
||||
E('thead', {}, E('tr', {}, [
|
||||
E('th', {}, 'Time'),
|
||||
E('th', {}, 'Source IP'),
|
||||
E('th', {}, 'Scenario'),
|
||||
E('th', {}, 'CVE'),
|
||||
E('th', {}, 'Severity')
|
||||
])),
|
||||
E('tbody', {}, threats.slice(0, 10).map(function(t) {
|
||||
var src = t.source || {};
|
||||
var severity = api.getSeverityClass(t.scenario);
|
||||
var cveId = api.extractCVE(t.scenario);
|
||||
var cveCell = cveId ?
|
||||
E('a', {
|
||||
'class': 'ta-cve-link',
|
||||
'href': 'https://nvd.nist.gov/vuln/detail/' + cveId,
|
||||
'target': '_blank',
|
||||
'rel': 'noopener'
|
||||
}, cveId) :
|
||||
E('span', { 'class': 'ta-no-cve' }, '-');
|
||||
return E('tr', { 'class': cveId ? 'ta-cve-row' : '' }, [
|
||||
E('td', { 'class': 'ta-time' }, api.formatRelativeTime(t.created_at)),
|
||||
E('td', {}, E('span', { 'class': 'ta-ip' }, src.ip || '-')),
|
||||
E('td', {}, E('span', { 'class': 'ta-scenario' }, api.parseScenario(t.scenario))),
|
||||
E('td', {}, cveCell),
|
||||
E('td', {}, E('span', { 'class': 'ta-badge ' + severity }, severity))
|
||||
]);
|
||||
}))
|
||||
]);
|
||||
},
|
||||
|
||||
var chatCard = E('div', { 'class': 'ta-card ta-chat' }, [
|
||||
E('h3', {}, 'AI Security Chat'),
|
||||
E('div', { 'class': 'ta-chat-messages', 'id': 'chat-messages' },
|
||||
renderChat: function() {
|
||||
var self = this;
|
||||
return E('div', { 'class': 'ta-chat' }, [
|
||||
E('div', { 'class': 'ta-chat-messages', 'id': 'ta-chat-messages' }, [
|
||||
E('div', { 'class': 'ta-message ai' }, [
|
||||
E('div', { 'class': 'ta-message-bubble' }, 'Hello! I\'m your SecuBox Threat Analyst. Ask me about security threats, or request filter rules for mitmproxy, CrowdSec, or WAF.')
|
||||
E('div', { 'class': 'ta-message-bubble' },
|
||||
'Hello! I\'m your Threat Analyst AI. Ask me about security threats, ' +
|
||||
'or request rules for CrowdSec, mitmproxy, or WAF.'),
|
||||
E('div', { 'class': 'ta-message-time' }, 'System')
|
||||
])
|
||||
),
|
||||
]),
|
||||
E('div', { 'class': 'ta-chat-input' }, [
|
||||
E('input', {
|
||||
'type': 'text',
|
||||
'id': 'chat-input',
|
||||
'placeholder': 'Ask about threats or request rules...',
|
||||
'id': 'ta-chat-input',
|
||||
'placeholder': 'Ask about threats or request filter rules...',
|
||||
'keypress': function(e) { if (e.key === 'Enter') self.sendChat(); }
|
||||
}),
|
||||
E('button', { 'click': function() { self.sendChat(); } }, 'Send')
|
||||
])
|
||||
]);
|
||||
|
||||
var threatsCard = E('div', { 'class': 'ta-card ta-threats' }, [
|
||||
E('h3', {}, 'Recent Threats'),
|
||||
E('table', { 'class': 'ta-threats-table' }, [
|
||||
E('thead', {}, [
|
||||
E('tr', {}, [
|
||||
E('th', {}, 'Time'),
|
||||
E('th', {}, 'Source'),
|
||||
E('th', {}, 'Scenario'),
|
||||
E('th', {}, 'IP'),
|
||||
E('th', {}, 'Severity')
|
||||
])
|
||||
]),
|
||||
E('tbody', { 'id': 'threats-body' },
|
||||
threats.slice(0, 10).map(function(t) {
|
||||
var severity = 'medium';
|
||||
if (t.scenario && (t.scenario.includes('malware') || t.scenario.includes('exploit'))) severity = 'critical';
|
||||
else if (t.scenario && t.scenario.includes('scan')) severity = 'high';
|
||||
else if (t.scenario && t.scenario.includes('http')) severity = 'low';
|
||||
|
||||
return E('tr', {}, [
|
||||
E('td', {}, (t.created_at || '').substring(11, 19)),
|
||||
E('td', {}, (t.source || {}).ip || '-'),
|
||||
E('td', {}, t.scenario || '-'),
|
||||
E('td', {}, (t.source || {}).ip || '-'),
|
||||
E('td', {}, E('span', { 'class': 'ta-badge ' + severity }, severity))
|
||||
]);
|
||||
})
|
||||
)
|
||||
])
|
||||
]);
|
||||
|
||||
return E('div', {}, [
|
||||
style,
|
||||
E('h2', {}, 'Threat Analyst'),
|
||||
E('div', { 'class': 'ta-dashboard' }, [
|
||||
statusCard,
|
||||
pendingCard,
|
||||
chatCard,
|
||||
threatsCard
|
||||
E('button', {
|
||||
'class': 'ta-btn ta-btn-primary',
|
||||
'click': function() { self.sendChat(); }
|
||||
}, 'Send')
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
sendChat: function() {
|
||||
var input = document.getElementById('chat-input');
|
||||
var messages = document.getElementById('chat-messages');
|
||||
var input = document.getElementById('ta-chat-input');
|
||||
var messages = document.getElementById('ta-chat-messages');
|
||||
var message = input.value.trim();
|
||||
var self = this;
|
||||
|
||||
if (!message) return;
|
||||
|
||||
@ -197,26 +250,24 @@ return view.extend({
|
||||
input.value = '';
|
||||
messages.scrollTop = messages.scrollHeight;
|
||||
|
||||
// Add loading indicator
|
||||
var loading = E('div', { 'class': 'ta-message ai', 'id': 'chat-loading' }, [
|
||||
// Add loading
|
||||
var loading = E('div', { 'class': 'ta-message ai', 'id': 'ta-chat-loading' }, [
|
||||
E('div', { 'class': 'ta-message-bubble' }, 'Analyzing...')
|
||||
]);
|
||||
messages.appendChild(loading);
|
||||
|
||||
// Call API
|
||||
api.chat(message).then(function(result) {
|
||||
var loadingEl = document.getElementById('chat-loading');
|
||||
var loadingEl = document.getElementById('ta-chat-loading');
|
||||
if (loadingEl) loadingEl.remove();
|
||||
|
||||
var response = result.response || result.error || 'No response';
|
||||
|
||||
messages.appendChild(E('div', { 'class': 'ta-message ai' }, [
|
||||
E('div', { 'class': 'ta-message-bubble' }, response),
|
||||
E('div', { 'class': 'ta-message-time' }, new Date().toLocaleTimeString())
|
||||
]));
|
||||
messages.scrollTop = messages.scrollHeight;
|
||||
}).catch(function(err) {
|
||||
var loadingEl = document.getElementById('chat-loading');
|
||||
var loadingEl = document.getElementById('ta-chat-loading');
|
||||
if (loadingEl) loadingEl.remove();
|
||||
|
||||
messages.appendChild(E('div', { 'class': 'ta-message ai' }, [
|
||||
@ -225,7 +276,7 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
runCycle: function() {
|
||||
runAnalysis: function() {
|
||||
ui.showModal('Running Analysis', [
|
||||
E('p', { 'class': 'spinning' }, 'Running threat analysis cycle...')
|
||||
]);
|
||||
@ -233,31 +284,39 @@ return view.extend({
|
||||
api.runCycle().then(function() {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', {}, 'Analysis cycle started'), 'success');
|
||||
}).catch(function() {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', {}, 'Failed to start analysis'), 'error');
|
||||
});
|
||||
},
|
||||
|
||||
generateRules: function(target) {
|
||||
var targetName = target === 'all' ? 'All' : target;
|
||||
ui.showModal('Generating Rules', [
|
||||
E('p', { 'class': 'spinning' }, 'Generating ' + target + ' rules with AI...')
|
||||
E('p', { 'class': 'spinning' }, 'Generating ' + targetName + ' rules with AI...')
|
||||
]);
|
||||
|
||||
api.generateRules(target).then(function(result) {
|
||||
ui.hideModal();
|
||||
if (result.rules) {
|
||||
ui.addNotification(null, E('p', {}, 'Rules generated. Check pending queue.'), 'success');
|
||||
ui.addNotification(null, E('p', {}, 'Rules generated. Check pending queue for approval.'), 'success');
|
||||
window.location.reload();
|
||||
} else {
|
||||
ui.addNotification(null, E('p', {}, 'Failed to generate rules'), 'error');
|
||||
ui.addNotification(null, E('p', {}, 'No rules generated'), 'warning');
|
||||
}
|
||||
}).catch(function() {
|
||||
ui.hideModal();
|
||||
ui.addNotification(null, E('p', {}, 'Failed to generate rules'), 'error');
|
||||
});
|
||||
},
|
||||
|
||||
approveRule: function(id) {
|
||||
var self = this;
|
||||
api.approveRule(id).then(function(result) {
|
||||
if (result.success) {
|
||||
ui.addNotification(null, E('p', {}, 'Rule approved and applied'), 'success');
|
||||
window.location.reload();
|
||||
} else {
|
||||
ui.addNotification(null, E('p', {}, 'Failed to approve rule'), 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -269,6 +328,24 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
pollData: function() {
|
||||
var self = this;
|
||||
return api.getOverview().then(function(data) {
|
||||
var s = data.status || {};
|
||||
var pending = data.pending || [];
|
||||
var threats = data.threats || [];
|
||||
|
||||
var el = document.getElementById('ta-stats');
|
||||
if (el) dom.content(el, self.renderStats(s, pending));
|
||||
|
||||
el = document.getElementById('ta-pending');
|
||||
if (el) dom.content(el, self.renderPending(pending));
|
||||
|
||||
el = document.getElementById('ta-threats');
|
||||
if (el) dom.content(el, self.renderThreats(threats));
|
||||
});
|
||||
},
|
||||
|
||||
handleSaveApply: null,
|
||||
handleSave: null,
|
||||
handleReset: null
|
||||
|
||||
@ -61,10 +61,16 @@ EOF
|
||||
[ -f "$STATE_DIR/pending_rules.json" ] && \
|
||||
pending_count=$(jsonfilter -i "$STATE_DIR/pending_rules.json" -e '@[*]' 2>/dev/null | wc -l)
|
||||
|
||||
# Count recent threats
|
||||
# Count recent threats and CVE alerts
|
||||
threat_count=0
|
||||
command -v cscli >/dev/null 2>&1 && \
|
||||
threat_count=$(cscli alerts list -o json --since 1h 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
|
||||
cve_count=0
|
||||
if command -v cscli >/dev/null 2>&1; then
|
||||
alerts_json=$(cscli alerts list -o json --since 1h 2>/dev/null)
|
||||
threat_count=$(echo "$alerts_json" | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
|
||||
# Count CVE-related alerts
|
||||
cve_count=$(echo "$alerts_json" | grep -ic 'cve-' 2>/dev/null)
|
||||
[ -z "$cve_count" ] && cve_count=0
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
@ -75,7 +81,8 @@ EOF
|
||||
"localai_status": "$localai_status",
|
||||
"localai_url": "$localai_url",
|
||||
"pending_rules": $pending_count,
|
||||
"recent_threats": $threat_count
|
||||
"recent_threats": $threat_count,
|
||||
"cve_alerts": $cve_count
|
||||
}
|
||||
EOF
|
||||
;;
|
||||
|
||||
@ -8,7 +8,7 @@ Architecture: all
|
||||
Installed-Size: 71680
|
||||
Description: Comprehensive authentication and session management with captive portal, OAuth2/OIDC integration, voucher system, and time-based access control
|
||||
Filename: luci-app-auth-guardian_0.4.0-r3_all.ipk
|
||||
Size: 11735
|
||||
Size: 11736
|
||||
|
||||
Package: luci-app-bandwidth-manager
|
||||
Version: 0.5.0-r2
|
||||
@ -32,7 +32,7 @@ Architecture: all
|
||||
Installed-Size: 122880
|
||||
Description: Dashboard for managing local CDN caching proxy on OpenWrt
|
||||
Filename: luci-app-cdn-cache_0.5.0-r3_all.ipk
|
||||
Size: 23185
|
||||
Size: 23182
|
||||
|
||||
Package: luci-app-client-guardian
|
||||
Version: 0.4.0-r7
|
||||
@ -44,7 +44,7 @@ Architecture: all
|
||||
Installed-Size: 286720
|
||||
Description: Network Access Control with client monitoring, zone management, captive portal, parental controls, and SMS/email alerts
|
||||
Filename: luci-app-client-guardian_0.4.0-r7_all.ipk
|
||||
Size: 54535
|
||||
Size: 54536
|
||||
|
||||
Package: luci-app-crowdsec-dashboard
|
||||
Version: 0.7.0-r32
|
||||
@ -56,7 +56,7 @@ Architecture: all
|
||||
Installed-Size: 184320
|
||||
Description: Real-time security monitoring dashboard for CrowdSec on OpenWrt
|
||||
Filename: luci-app-crowdsec-dashboard_0.7.0-r32_all.ipk
|
||||
Size: 33740
|
||||
Size: 33739
|
||||
|
||||
Package: luci-app-cyberfeed
|
||||
Version: 0.1.1-r1
|
||||
@ -68,7 +68,7 @@ Architecture: all
|
||||
Installed-Size: 71680
|
||||
Description: Cyberpunk-themed RSS feed aggregator dashboard with social media support
|
||||
Filename: luci-app-cyberfeed_0.1.1-r1_all.ipk
|
||||
Size: 12839
|
||||
Size: 12837
|
||||
|
||||
Package: luci-app-device-intel
|
||||
Version: 1.0.0-r1
|
||||
@ -80,7 +80,7 @@ Architecture: all
|
||||
Installed-Size: 61440
|
||||
Description: LuCI SecuBox Device Intelligence
|
||||
Filename: luci-app-device-intel_1.0.0-r1_all.ipk
|
||||
Size: 10862
|
||||
Size: 10859
|
||||
|
||||
Package: luci-app-dnsguard
|
||||
Version: 1.1.0-r1
|
||||
@ -111,7 +111,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: LuCI DNS Provider Manager
|
||||
Filename: luci-app-dns-provider_1.0.0-r1_all.ipk
|
||||
Size: 7127
|
||||
Size: 7130
|
||||
|
||||
Package: luci-app-exposure
|
||||
Version: 1.0.0-r3
|
||||
@ -123,7 +123,7 @@ Architecture: all
|
||||
Installed-Size: 61440
|
||||
Description: LuCI SecuBox Service Exposure Manager
|
||||
Filename: luci-app-exposure_1.0.0-r3_all.ipk
|
||||
Size: 9838
|
||||
Size: 9841
|
||||
|
||||
Package: luci-app-gitea
|
||||
Version: 1.0.0-r2
|
||||
@ -135,7 +135,7 @@ Architecture: all
|
||||
Installed-Size: 81920
|
||||
Description: Modern dashboard for Gitea Platform management on OpenWrt
|
||||
Filename: luci-app-gitea_1.0.0-r2_all.ipk
|
||||
Size: 15299
|
||||
Size: 15300
|
||||
|
||||
Package: luci-app-glances
|
||||
Version: 1.0.0-r2
|
||||
@ -147,7 +147,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: Modern dashboard for Glances system monitoring with SecuBox theme
|
||||
Filename: luci-app-glances_1.0.0-r2_all.ipk
|
||||
Size: 6968
|
||||
Size: 6969
|
||||
|
||||
Package: luci-app-haproxy
|
||||
Version: 1.0.0-r8
|
||||
@ -171,7 +171,7 @@ Architecture: all
|
||||
Installed-Size: 184320
|
||||
Description: Modern dashboard for Hexo static site generator on OpenWrt
|
||||
Filename: luci-app-hexojs_1.0.0-r3_all.ipk
|
||||
Size: 30311
|
||||
Size: 30307
|
||||
|
||||
Package: luci-app-jellyfin
|
||||
Version: 1.0.0-r1
|
||||
@ -183,7 +183,7 @@ Architecture: all
|
||||
Installed-Size: 30720
|
||||
Description: LuCI Jellyfin Media Server Configuration
|
||||
Filename: luci-app-jellyfin_1.0.0-r1_all.ipk
|
||||
Size: 6060
|
||||
Size: 6061
|
||||
|
||||
Package: luci-app-jitsi
|
||||
Version: 1.0.0-r1
|
||||
@ -195,7 +195,7 @@ Architecture: all
|
||||
Installed-Size: 30720
|
||||
Description: LuCI Jitsi Meet Configuration
|
||||
Filename: luci-app-jitsi_1.0.0-r1_all.ipk
|
||||
Size: 5139
|
||||
Size: 5134
|
||||
|
||||
Package: luci-app-ksm-manager
|
||||
Version: 0.4.0-r2
|
||||
@ -207,7 +207,7 @@ Architecture: all
|
||||
Installed-Size: 112640
|
||||
Description: Centralized cryptographic key management with hardware security module (HSM) support for Nitrokey and YubiKey devices. Provides secure key storage, certificate management, SSH key handling, and secret storage with audit logging.
|
||||
Filename: luci-app-ksm-manager_0.4.0-r2_all.ipk
|
||||
Size: 18724
|
||||
Size: 18719
|
||||
|
||||
Package: luci-app-localai
|
||||
Version: 0.1.0-r15
|
||||
@ -219,7 +219,7 @@ Architecture: all
|
||||
Installed-Size: 71680
|
||||
Description: Modern dashboard for LocalAI LLM management on OpenWrt
|
||||
Filename: luci-app-localai_0.1.0-r15_all.ipk
|
||||
Size: 13181
|
||||
Size: 13182
|
||||
|
||||
Package: luci-app-lyrion
|
||||
Version: 1.0.0-r1
|
||||
@ -231,7 +231,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: LuCI support for Lyrion Music Server
|
||||
Filename: luci-app-lyrion_1.0.0-r1_all.ipk
|
||||
Size: 6727
|
||||
Size: 6725
|
||||
|
||||
Package: luci-app-mac-guardian
|
||||
Version: 0.5.0-r1
|
||||
@ -243,7 +243,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: LuCI MAC Guardian - WiFi MAC Security Monitor
|
||||
Filename: luci-app-mac-guardian_0.5.0-r1_all.ipk
|
||||
Size: 6512
|
||||
Size: 6509
|
||||
|
||||
Package: luci-app-magicmirror2
|
||||
Version: 0.4.0-r6
|
||||
@ -279,7 +279,7 @@ Architecture: all
|
||||
Installed-Size: 30720
|
||||
Description: LuCI SecuBox Master-Link Mesh Management
|
||||
Filename: luci-app-master-link_1.0.0-r1_all.ipk
|
||||
Size: 6248
|
||||
Size: 6245
|
||||
|
||||
Package: luci-app-media-flow
|
||||
Version: 0.6.4-r1
|
||||
@ -291,7 +291,7 @@ Architecture: all
|
||||
Installed-Size: 133120
|
||||
Description: Real-time detection and monitoring of streaming services (Netflix, YouTube, Spotify, etc.) with quality estimation, history tracking, and alerts. Supports nDPId local DPI and netifyd.
|
||||
Filename: luci-app-media-flow_0.6.4-r1_all.ipk
|
||||
Size: 25416
|
||||
Size: 25418
|
||||
|
||||
Package: luci-app-metablogizer
|
||||
Version: 1.0.0-r5
|
||||
@ -327,7 +327,7 @@ Architecture: all
|
||||
Installed-Size: 61440
|
||||
Description: Modern dashboard for mitmproxy HTTPS traffic inspection with SecuBox theme
|
||||
Filename: luci-app-mitmproxy_0.5.0-r2_all.ipk
|
||||
Size: 11152
|
||||
Size: 11149
|
||||
|
||||
Package: luci-app-mmpm
|
||||
Version: 0.2.0-r3
|
||||
@ -339,7 +339,7 @@ Architecture: all
|
||||
Installed-Size: 51200
|
||||
Description: Web interface for MMPM - MagicMirror Package Manager
|
||||
Filename: luci-app-mmpm_0.2.0-r3_all.ipk
|
||||
Size: 7901
|
||||
Size: 7899
|
||||
|
||||
Package: luci-app-mqtt-bridge
|
||||
Version: 0.4.0-r4
|
||||
@ -351,7 +351,7 @@ Architecture: all
|
||||
Installed-Size: 122880
|
||||
Description: USB-to-MQTT IoT hub with SecuBox theme
|
||||
Filename: luci-app-mqtt-bridge_0.4.0-r4_all.ipk
|
||||
Size: 22779
|
||||
Size: 22780
|
||||
|
||||
Package: luci-app-ndpid
|
||||
Version: 1.1.2-r2
|
||||
@ -363,7 +363,7 @@ Architecture: all
|
||||
Installed-Size: 122880
|
||||
Description: Modern dashboard for nDPId deep packet inspection on OpenWrt
|
||||
Filename: luci-app-ndpid_1.1.2-r2_all.ipk
|
||||
Size: 22653
|
||||
Size: 22654
|
||||
|
||||
Package: luci-app-netdata-dashboard
|
||||
Version: 0.5.0-r2
|
||||
@ -375,7 +375,7 @@ Architecture: all
|
||||
Installed-Size: 112640
|
||||
Description: Real-time system monitoring dashboard with Netdata integration for OpenWrt
|
||||
Filename: luci-app-netdata-dashboard_0.5.0-r2_all.ipk
|
||||
Size: 20488
|
||||
Size: 20484
|
||||
|
||||
Package: luci-app-network-modes
|
||||
Version: 0.5.0-r3
|
||||
@ -387,7 +387,7 @@ Architecture: all
|
||||
Installed-Size: 286720
|
||||
Description: Configure OpenWrt for different network modes: Sniffer, Access Point, Relay, Router
|
||||
Filename: luci-app-network-modes_0.5.0-r3_all.ipk
|
||||
Size: 54148
|
||||
Size: 54149
|
||||
|
||||
Package: luci-app-network-tweaks
|
||||
Version: 1.0.0-r7
|
||||
@ -399,7 +399,7 @@ Architecture: all
|
||||
Installed-Size: 81920
|
||||
Description: Unified network services dashboard with DNS/hosts sync, CDN cache control, and WPAD auto-proxy configuration
|
||||
Filename: luci-app-network-tweaks_1.0.0-r7_all.ipk
|
||||
Size: 14960
|
||||
Size: 14957
|
||||
|
||||
Package: luci-app-nextcloud
|
||||
Version: 1.0.0-r1
|
||||
@ -411,7 +411,7 @@ Architecture: all
|
||||
Installed-Size: 30720
|
||||
Description: LuCI support for Nextcloud
|
||||
Filename: luci-app-nextcloud_1.0.0-r1_all.ipk
|
||||
Size: 6486
|
||||
Size: 6489
|
||||
|
||||
Package: luci-app-ollama
|
||||
Version: 0.1.0-r1
|
||||
@ -423,7 +423,7 @@ Architecture: all
|
||||
Installed-Size: 61440
|
||||
Description: Modern dashboard for Ollama LLM management on OpenWrt
|
||||
Filename: luci-app-ollama_0.1.0-r1_all.ipk
|
||||
Size: 12355
|
||||
Size: 12352
|
||||
|
||||
Package: luci-app-picobrew
|
||||
Version: 1.0.0-r1
|
||||
@ -435,7 +435,7 @@ Architecture: all
|
||||
Installed-Size: 51200
|
||||
Description: Modern dashboard for PicoBrew Server management on OpenWrt
|
||||
Filename: luci-app-picobrew_1.0.0-r1_all.ipk
|
||||
Size: 9458
|
||||
Size: 9459
|
||||
|
||||
Package: luci-app-secubox
|
||||
Version: 0.7.1-r4
|
||||
@ -458,7 +458,7 @@ Architecture: all
|
||||
Installed-Size: 337920
|
||||
Description: Unified admin control center for SecuBox appstore plugins with system monitoring
|
||||
Filename: luci-app-secubox-admin_1.0.0-r19_all.ipk
|
||||
Size: 57247
|
||||
Size: 57245
|
||||
|
||||
Package: luci-app-secubox-crowdsec
|
||||
Version: 1.0.0-r3
|
||||
@ -470,7 +470,7 @@ Architecture: all
|
||||
Installed-Size: 81920
|
||||
Description: LuCI SecuBox CrowdSec Dashboard
|
||||
Filename: luci-app-secubox-crowdsec_1.0.0-r3_all.ipk
|
||||
Size: 13917
|
||||
Size: 13923
|
||||
|
||||
Package: luci-app-secubox-netdiag
|
||||
Version: 1.0.0-r1
|
||||
@ -482,7 +482,7 @@ Architecture: all
|
||||
Installed-Size: 81920
|
||||
Description: Real-time DSA switch port statistics, error monitoring, and network health diagnostics
|
||||
Filename: luci-app-secubox-netdiag_1.0.0-r1_all.ipk
|
||||
Size: 15308
|
||||
Size: 15306
|
||||
|
||||
Package: luci-app-secubox-netifyd
|
||||
Version: 1.2.1-r1
|
||||
@ -506,7 +506,7 @@ Architecture: all
|
||||
Installed-Size: 235520
|
||||
Description: LuCI SecuBox P2P Hub
|
||||
Filename: luci-app-secubox-p2p_0.1.0-r1_all.ipk
|
||||
Size: 44085
|
||||
Size: 44086
|
||||
|
||||
Package: luci-app-secubox-portal
|
||||
Version: 0.7.0-r2
|
||||
@ -518,7 +518,7 @@ Architecture: all
|
||||
Installed-Size: 122880
|
||||
Description: Unified entry point for all SecuBox applications with tabbed navigation
|
||||
Filename: luci-app-secubox-portal_0.7.0-r2_all.ipk
|
||||
Size: 24646
|
||||
Size: 24644
|
||||
|
||||
Package: luci-app-secubox-security-threats
|
||||
Version: 1.0.0-r4
|
||||
@ -542,7 +542,7 @@ Architecture: all
|
||||
Installed-Size: 194560
|
||||
Description: Unified service aggregation with HAProxy vhosts, Tor hidden services, and QR-coded landing page
|
||||
Filename: luci-app-service-registry_1.0.0-r1_all.ipk
|
||||
Size: 39826
|
||||
Size: 39828
|
||||
|
||||
Package: luci-app-simplex
|
||||
Version: 1.0.0-r1
|
||||
@ -554,7 +554,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: LuCI SimpleX Chat Server Configuration
|
||||
Filename: luci-app-simplex_1.0.0-r1_all.ipk
|
||||
Size: 6999
|
||||
Size: 7000
|
||||
|
||||
Package: luci-app-streamlit
|
||||
Version: 1.0.0-r11
|
||||
@ -566,7 +566,7 @@ Architecture: all
|
||||
Installed-Size: 81920
|
||||
Description: Multi-instance Streamlit management with Gitea integration
|
||||
Filename: luci-app-streamlit_1.0.0-r11_all.ipk
|
||||
Size: 14748
|
||||
Size: 14749
|
||||
|
||||
Package: luci-app-system-hub
|
||||
Version: 0.5.1-r4
|
||||
@ -578,7 +578,7 @@ Architecture: all
|
||||
Installed-Size: 317440
|
||||
Description: Central system control with monitoring, services, logs, and backup
|
||||
Filename: luci-app-system-hub_0.5.1-r4_all.ipk
|
||||
Size: 61106
|
||||
Size: 61105
|
||||
|
||||
Package: luci-app-threat-analyst
|
||||
Version: 1.0.0-r1
|
||||
@ -587,10 +587,10 @@ License: MIT
|
||||
Section: luci
|
||||
Maintainer: OpenWrt LuCI community
|
||||
Architecture: all
|
||||
Installed-Size: 40960
|
||||
Installed-Size: 51200
|
||||
Description: LuCI Threat Analyst Dashboard
|
||||
Filename: luci-app-threat-analyst_1.0.0-r1_all.ipk
|
||||
Size: 6951
|
||||
Size: 9753
|
||||
|
||||
Package: luci-app-tor-shield
|
||||
Version: 1.0.0-r10
|
||||
@ -602,7 +602,7 @@ Architecture: all
|
||||
Installed-Size: 122880
|
||||
Description: Modern dashboard for Tor anonymization on OpenWrt
|
||||
Filename: luci-app-tor-shield_1.0.0-r10_all.ipk
|
||||
Size: 22361
|
||||
Size: 22362
|
||||
|
||||
Package: luci-app-traffic-shaper
|
||||
Version: 0.4.0-r2
|
||||
@ -614,7 +614,7 @@ Architecture: all
|
||||
Installed-Size: 81920
|
||||
Description: Advanced traffic shaping with TC/CAKE for precise bandwidth control
|
||||
Filename: luci-app-traffic-shaper_0.4.0-r2_all.ipk
|
||||
Size: 14537
|
||||
Size: 14535
|
||||
|
||||
Package: luci-app-vhost-manager
|
||||
Version: 0.5.0-r5
|
||||
@ -626,7 +626,7 @@ Architecture: all
|
||||
Installed-Size: 153600
|
||||
Description: Nginx reverse proxy manager with Let's Encrypt SSL certificates, authentication, and WebSocket support
|
||||
Filename: luci-app-vhost-manager_0.5.0-r5_all.ipk
|
||||
Size: 26181
|
||||
Size: 26186
|
||||
|
||||
Package: luci-app-wireguard-dashboard
|
||||
Version: 0.7.0-r5
|
||||
@ -638,7 +638,7 @@ Architecture: all
|
||||
Installed-Size: 204800
|
||||
Description: Modern dashboard for WireGuard VPN monitoring on OpenWrt
|
||||
Filename: luci-app-wireguard-dashboard_0.7.0-r5_all.ipk
|
||||
Size: 39609
|
||||
Size: 39607
|
||||
|
||||
Package: luci-app-zigbee2mqtt
|
||||
Version: 1.0.0-r2
|
||||
@ -650,7 +650,7 @@ Architecture: all
|
||||
Installed-Size: 40960
|
||||
Description: Graphical interface for managing the Zigbee2MQTT docker application.
|
||||
Filename: luci-app-zigbee2mqtt_1.0.0-r2_all.ipk
|
||||
Size: 6815
|
||||
Size: 6813
|
||||
|
||||
Package: luci-theme-secubox
|
||||
Version: 0.4.7-r1
|
||||
@ -662,7 +662,7 @@ Architecture: all
|
||||
Installed-Size: 450560
|
||||
Description: Global CyberMood design system (CSS/JS/i18n) shared by all SecuBox dashboards.
|
||||
Filename: luci-theme-secubox_0.4.7-r1_all.ipk
|
||||
Size: 110241
|
||||
Size: 110239
|
||||
|
||||
Package: secubox-app
|
||||
Version: 1.0.0-r2
|
||||
@ -673,7 +673,7 @@ Installed-Size: 92160
|
||||
Description: Command line helper for SecuBox App Store manifests. Installs /usr/sbin/secubox-app
|
||||
and ships the default manifests under /usr/share/secubox/plugins/.
|
||||
Filename: secubox-app_1.0.0-r2_all.ipk
|
||||
Size: 11182
|
||||
Size: 11184
|
||||
|
||||
Package: secubox-app-adguardhome
|
||||
Version: 1.0.0-r2
|
||||
@ -687,7 +687,7 @@ Description: Installer, configuration, and service manager for running AdGuard
|
||||
inside Docker on SecuBox-powered OpenWrt systems. Network-wide ad blocker
|
||||
with DNS-over-HTTPS/TLS support and detailed analytics.
|
||||
Filename: secubox-app-adguardhome_1.0.0-r2_all.ipk
|
||||
Size: 2882
|
||||
Size: 2880
|
||||
|
||||
Package: secubox-app-auth-logger
|
||||
Version: 1.2.2-r1
|
||||
@ -705,7 +705,7 @@ Description: Logs authentication failures from LuCI/rpcd and Dropbear SSH
|
||||
- JavaScript hook to intercept login failures
|
||||
- CrowdSec parser and bruteforce scenario
|
||||
Filename: secubox-app-auth-logger_1.2.2-r1_all.ipk
|
||||
Size: 9375
|
||||
Size: 9379
|
||||
|
||||
Package: secubox-app-crowdsec-custom
|
||||
Version: 1.1.0-r1
|
||||
@ -728,7 +728,7 @@ Description: Custom CrowdSec configurations for SecuBox web interface protectio
|
||||
- Webapp generic auth bruteforce protection
|
||||
- Whitelist for trusted networks
|
||||
Filename: secubox-app-crowdsec-custom_1.1.0-r1_all.ipk
|
||||
Size: 5758
|
||||
Size: 5761
|
||||
|
||||
Package: secubox-app-cs-firewall-bouncer
|
||||
Version: 0.0.31-r4
|
||||
@ -755,7 +755,7 @@ Description: SecuBox CrowdSec Firewall Bouncer for OpenWrt.
|
||||
- Automatic restart on firewall reload
|
||||
- procd service management
|
||||
Filename: secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk
|
||||
Size: 5049326
|
||||
Size: 5049328
|
||||
|
||||
Package: secubox-app-cyberfeed
|
||||
Version: 0.2.1-r1
|
||||
@ -769,7 +769,7 @@ Description: Cyberpunk-themed RSS feed aggregator for OpenWrt/SecuBox.
|
||||
Features emoji injection, neon styling, and RSS-Bridge support
|
||||
for social media feeds (Facebook, Twitter, Mastodon).
|
||||
Filename: secubox-app-cyberfeed_0.2.1-r1_all.ipk
|
||||
Size: 12453
|
||||
Size: 12454
|
||||
|
||||
Package: secubox-app-device-intel
|
||||
Version: 1.0.0-r1
|
||||
@ -783,7 +783,7 @@ Description: Unified device inventory aggregating mac-guardian, client-guardian
|
||||
P2P mesh, and exposure scanner data. Includes heuristic classification
|
||||
and pluggable emulator modules for MQTT, Zigbee, and USB devices.
|
||||
Filename: secubox-app-device-intel_1.0.0-r1_all.ipk
|
||||
Size: 13005
|
||||
Size: 13004
|
||||
|
||||
Package: secubox-app-dns-provider
|
||||
Version: 1.0.0-r1
|
||||
@ -797,7 +797,7 @@ Description: Programmatic DNS record management via provider APIs (OVH, Gandi
|
||||
Cloudflare). Provides the dnsctl CLI for record CRUD, zone sync
|
||||
DNS propagation verification, and ACME DNS-01 challenge support.
|
||||
Filename: secubox-app-dns-provider_1.0.0-r1_all.ipk
|
||||
Size: 5590
|
||||
Size: 6702
|
||||
|
||||
Package: secubox-app-domoticz
|
||||
Version: 1.0.0-r2
|
||||
@ -810,7 +810,7 @@ Installed-Size: 10240
|
||||
Description: Installer, configuration, and service manager for running Domoticz
|
||||
inside Docker on SecuBox-powered OpenWrt systems.
|
||||
Filename: secubox-app-domoticz_1.0.0-r2_all.ipk
|
||||
Size: 2546
|
||||
Size: 2548
|
||||
|
||||
Package: secubox-app-exposure
|
||||
Version: 1.0.0-r1
|
||||
@ -825,7 +825,7 @@ Description: Unified service exposure manager for SecuBox.
|
||||
- Dynamic Tor hidden service management
|
||||
- HAProxy SSL reverse proxy configuration
|
||||
Filename: secubox-app-exposure_1.0.0-r1_all.ipk
|
||||
Size: 6936
|
||||
Size: 6934
|
||||
|
||||
Package: secubox-app-gitea
|
||||
Version: 1.0.0-r5
|
||||
@ -848,7 +848,7 @@ Description: Gitea Git Platform - Self-hosted lightweight Git service
|
||||
Runs in LXC container with Alpine Linux.
|
||||
Configure in /etc/config/gitea.
|
||||
Filename: secubox-app-gitea_1.0.0-r5_all.ipk
|
||||
Size: 9402
|
||||
Size: 9407
|
||||
|
||||
Package: secubox-app-glances
|
||||
Version: 1.0.0-r1
|
||||
@ -871,7 +871,7 @@ Description: Glances - Cross-platform system monitoring tool for SecuBox.
|
||||
Runs in LXC container for isolation and security.
|
||||
Configure in /etc/config/glances.
|
||||
Filename: secubox-app-glances_1.0.0-r1_all.ipk
|
||||
Size: 5536
|
||||
Size: 5538
|
||||
|
||||
Package: secubox-app-haproxy
|
||||
Version: 1.0.0-r23
|
||||
@ -891,7 +891,7 @@ Description: HAProxy load balancer and reverse proxy running in an LXC containe
|
||||
- Stats dashboard
|
||||
- Rate limiting and ACLs
|
||||
Filename: secubox-app-haproxy_1.0.0-r23_all.ipk
|
||||
Size: 15683
|
||||
Size: 15687
|
||||
|
||||
Package: secubox-app-hexojs
|
||||
Version: 1.0.0-r8
|
||||
@ -915,7 +915,7 @@ Description: Hexo CMS - Self-hosted static blog generator for OpenWrt
|
||||
Runs in LXC container with Alpine Linux.
|
||||
Configure in /etc/config/hexojs.
|
||||
Filename: secubox-app-hexojs_1.0.0-r8_all.ipk
|
||||
Size: 94937
|
||||
Size: 94940
|
||||
|
||||
Package: secubox-app-jellyfin
|
||||
Version: 1.0.0-r1
|
||||
@ -929,7 +929,7 @@ Description: Installer, configuration, and service manager for running Jellyfin
|
||||
inside Docker on SecuBox-powered OpenWrt systems. Free media server
|
||||
for streaming movies, TV shows, music, and photos.
|
||||
Filename: secubox-app-jellyfin_1.0.0-r1_all.ipk
|
||||
Size: 6182
|
||||
Size: 6185
|
||||
|
||||
Package: secubox-app-jitsi
|
||||
Version: 1.0.0-r1
|
||||
@ -954,7 +954,7 @@ Description: Jitsi Meet - Secure, fully featured video conferencing for SecuBox
|
||||
Integrates with HAProxy for SSL termination.
|
||||
Configure in /etc/config/jitsi.
|
||||
Filename: secubox-app-jitsi_1.0.0-r1_all.ipk
|
||||
Size: 8913
|
||||
Size: 8914
|
||||
|
||||
Package: secubox-app-localai
|
||||
Version: 2.25.0-r1
|
||||
@ -976,7 +976,7 @@ Description: LocalAI native binary package for OpenWrt.
|
||||
|
||||
API: http://<router-ip>:8081/v1
|
||||
Filename: secubox-app-localai_2.25.0-r1_all.ipk
|
||||
Size: 5722
|
||||
Size: 5720
|
||||
|
||||
Package: secubox-app-localai-wb
|
||||
Version: 2.25.0-r1
|
||||
@ -1000,7 +1000,7 @@ Description: LocalAI native binary package for OpenWrt.
|
||||
|
||||
API: http://<router-ip>:8080/v1
|
||||
Filename: secubox-app-localai-wb_2.25.0-r1_all.ipk
|
||||
Size: 7953
|
||||
Size: 7951
|
||||
|
||||
Package: secubox-app-lyrion
|
||||
Version: 2.0.2-r1
|
||||
@ -1020,7 +1020,7 @@ Description: Lyrion Media Server (formerly Logitech Media Server / Squeezebox S
|
||||
Auto-detects available runtime, preferring LXC for lower resource usage.
|
||||
Configure runtime in /etc/config/lyrion.
|
||||
Filename: secubox-app-lyrion_2.0.2-r1_all.ipk
|
||||
Size: 7288
|
||||
Size: 7287
|
||||
|
||||
Package: secubox-app-mac-guardian
|
||||
Version: 0.5.0-r1
|
||||
@ -1035,7 +1035,7 @@ Description: WiFi MAC address security monitor for SecuBox.
|
||||
and spoofing. Integrates with CrowdSec and provides
|
||||
real-time hostapd hotplug detection.
|
||||
Filename: secubox-app-mac-guardian_0.5.0-r1_all.ipk
|
||||
Size: 12095
|
||||
Size: 12099
|
||||
|
||||
Package: secubox-app-magicmirror2
|
||||
Version: 0.4.0-r8
|
||||
@ -1057,7 +1057,7 @@ Description: MagicMirror² - Open source modular smart mirror platform for Secu
|
||||
Runs in LXC container for isolation and security.
|
||||
Configure in /etc/config/magicmirror2.
|
||||
Filename: secubox-app-magicmirror2_0.4.0-r8_all.ipk
|
||||
Size: 9254
|
||||
Size: 9253
|
||||
|
||||
Package: secubox-app-mailinabox
|
||||
Version: 2.0.0-r1
|
||||
@ -1082,7 +1082,7 @@ Description: Complete email server solution using docker-mailserver for SecuBox
|
||||
|
||||
Commands: mailinaboxctl --help
|
||||
Filename: secubox-app-mailinabox_2.0.0-r1_all.ipk
|
||||
Size: 7571
|
||||
Size: 7572
|
||||
|
||||
Package: secubox-app-metabolizer
|
||||
Version: 1.0.0-r3
|
||||
@ -1130,7 +1130,7 @@ Description: mitmproxy - Interactive HTTPS proxy for SecuBox-powered OpenWrt sy
|
||||
Runs in LXC container for isolation and security.
|
||||
Configure in /etc/config/mitmproxy.
|
||||
Filename: secubox-app-mitmproxy_0.5.0-r19_all.ipk
|
||||
Size: 22954
|
||||
Size: 22962
|
||||
|
||||
Package: secubox-app-mmpm
|
||||
Version: 0.2.0-r5
|
||||
@ -1151,7 +1151,7 @@ Description: MMPM (MagicMirror Package Manager) for SecuBox.
|
||||
|
||||
Runs inside the MagicMirror2 LXC container.
|
||||
Filename: secubox-app-mmpm_0.2.0-r5_all.ipk
|
||||
Size: 3977
|
||||
Size: 3975
|
||||
|
||||
Package: secubox-app-nextcloud
|
||||
Version: 1.0.0-r2
|
||||
@ -1165,7 +1165,7 @@ Description: Installer, configuration, and service manager for running Nextclou
|
||||
inside Docker on SecuBox-powered OpenWrt systems. Self-hosted file
|
||||
sync and share with calendar, contacts, and collaboration.
|
||||
Filename: secubox-app-nextcloud_1.0.0-r2_all.ipk
|
||||
Size: 2955
|
||||
Size: 2958
|
||||
|
||||
Package: secubox-app-ollama
|
||||
Version: 0.1.0-r1
|
||||
@ -1187,7 +1187,7 @@ Description: Ollama - Simple local LLM runtime for SecuBox-powered OpenWrt syst
|
||||
Runs in Docker/Podman container.
|
||||
Configure in /etc/config/ollama.
|
||||
Filename: secubox-app-ollama_0.1.0-r1_all.ipk
|
||||
Size: 5736
|
||||
Size: 5739
|
||||
|
||||
Package: secubox-app-picobrew
|
||||
Version: 1.0.0-r7
|
||||
@ -1209,7 +1209,7 @@ Description: PicoBrew Server - Self-hosted brewing controller for PicoBrew devi
|
||||
Runs in LXC container with Python/Flask backend.
|
||||
Configure in /etc/config/picobrew.
|
||||
Filename: secubox-app-picobrew_1.0.0-r7_all.ipk
|
||||
Size: 5539
|
||||
Size: 5540
|
||||
|
||||
Package: secubox-app-simplex
|
||||
Version: 1.0.0-r1
|
||||
@ -1233,7 +1233,7 @@ Description: SimpleX Chat self-hosted messaging infrastructure for SecuBox.
|
||||
Privacy-first messaging relay that you control.
|
||||
Configure in /etc/config/simplex.
|
||||
Filename: secubox-app-simplex_1.0.0-r1_all.ipk
|
||||
Size: 9233
|
||||
Size: 9235
|
||||
|
||||
Package: secubox-app-streamlit
|
||||
Version: 1.0.0-r5
|
||||
@ -1283,7 +1283,7 @@ Description: SecuBox Tor Shield - One-click Tor anonymization for OpenWrt
|
||||
|
||||
Configure in /etc/config/tor-shield.
|
||||
Filename: secubox-app-tor_1.0.0-r1_all.ipk
|
||||
Size: 7370
|
||||
Size: 7371
|
||||
|
||||
Package: secubox-app-webapp
|
||||
Version: 1.5.0-r7
|
||||
@ -1301,7 +1301,7 @@ Description: SecuBox Control Center Dashboard - A web-based dashboard for monit
|
||||
- Service management
|
||||
- Network interface control
|
||||
Filename: secubox-app-webapp_1.5.0-r7_all.ipk
|
||||
Size: 39173
|
||||
Size: 39175
|
||||
|
||||
Package: secubox-app-zigbee2mqtt
|
||||
Version: 1.0.0-r3
|
||||
@ -1314,7 +1314,7 @@ Installed-Size: 20480
|
||||
Description: Installer, configuration, and service manager for running Zigbee2MQTT
|
||||
inside an Alpine LXC container on SecuBox-powered OpenWrt systems.
|
||||
Filename: secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk
|
||||
Size: 5507
|
||||
Size: 5510
|
||||
|
||||
Package: secubox-core
|
||||
Version: 0.10.0-r11
|
||||
@ -1334,7 +1334,7 @@ Description: SecuBox Core Framework provides the foundational infrastructure fo
|
||||
- Unified CLI interface
|
||||
- ubus RPC backend
|
||||
Filename: secubox-core_0.10.0-r11_all.ipk
|
||||
Size: 87977
|
||||
Size: 87975
|
||||
|
||||
Package: secubox-dns-guard
|
||||
Version: 1.0.0-r1
|
||||
@ -1353,7 +1353,7 @@ Description: SecuBox DNS Guard provides AI-powered DNS anomaly detection using
|
||||
- Unusual TLD pattern detection
|
||||
- Automatic blocklist generation with approval workflow
|
||||
Filename: secubox-dns-guard_1.0.0-r1_all.ipk
|
||||
Size: 12476
|
||||
Size: 12473
|
||||
|
||||
Package: secubox-master-link
|
||||
Version: 1.0.0-r1
|
||||
@ -1375,7 +1375,7 @@ Description: Secure mesh onboarding for SecuBox nodes via master/peer link.
|
||||
|
||||
Configure in /etc/config/master-link.
|
||||
Filename: secubox-master-link_1.0.0-r1_all.ipk
|
||||
Size: 12453
|
||||
Size: 12456
|
||||
|
||||
Package: secubox-mcp-server
|
||||
Version: 1.0.0-r1
|
||||
@ -1403,7 +1403,7 @@ Description: Model Context Protocol (MCP) server for SecuBox.
|
||||
- ai.explain_ban (Explain CrowdSec decisions)
|
||||
- ai.security_posture (Security assessment)
|
||||
Filename: secubox-mcp-server_1.0.0-r1_all.ipk
|
||||
Size: 11430
|
||||
Size: 11431
|
||||
|
||||
Package: secubox-p2p
|
||||
Version: 0.6.0-r3
|
||||
@ -1422,7 +1422,7 @@ Description: SecuBox P2P Hub backend providing peer discovery, mesh networking
|
||||
and MirrorBox NetMesh Catalog for cross-chain distributed service
|
||||
registry with HAProxy vhost discovery and multi-endpoint access URLs.
|
||||
Filename: secubox-p2p_0.6.0-r3_all.ipk
|
||||
Size: 47675
|
||||
Size: 47677
|
||||
|
||||
Package: secubox-threat-analyst
|
||||
Version: 1.0.0-r1
|
||||
@ -1441,5 +1441,5 @@ Description: Autonomous threat analysis agent for SecuBox.
|
||||
|
||||
Part of SecuBox AI Gateway (Couche 2).
|
||||
Filename: secubox-threat-analyst_1.0.0-r1_all.ipk
|
||||
Size: 9868
|
||||
Size: 9867
|
||||
|
||||
|
||||
Binary file not shown.
@ -1,12 +1,12 @@
|
||||
{
|
||||
"feed_url": "/secubox-feed",
|
||||
"generated": "2026-02-05T06:06:11+01:00",
|
||||
"generated": "2026-02-05T09:12:05+01:00",
|
||||
"packages": [
|
||||
{
|
||||
"name": "luci-app-auth-guardian",
|
||||
"version": "0.4.0-r3",
|
||||
"filename": "luci-app-auth-guardian_0.4.0-r3_all.ipk",
|
||||
"size": 11735,
|
||||
"size": 11736,
|
||||
"category": "security",
|
||||
"icon": "key",
|
||||
"description": "Authentication management",
|
||||
@ -30,7 +30,7 @@
|
||||
"name": "luci-app-cdn-cache",
|
||||
"version": "0.5.0-r3",
|
||||
"filename": "luci-app-cdn-cache_0.5.0-r3_all.ipk",
|
||||
"size": 23185,
|
||||
"size": 23182,
|
||||
"category": "network",
|
||||
"icon": "globe",
|
||||
"description": "CDN caching",
|
||||
@ -42,7 +42,7 @@
|
||||
"name": "luci-app-client-guardian",
|
||||
"version": "0.4.0-r7",
|
||||
"filename": "luci-app-client-guardian_0.4.0-r7_all.ipk",
|
||||
"size": 54535,
|
||||
"size": 54536,
|
||||
"category": "network",
|
||||
"icon": "users",
|
||||
"description": "Client management and monitoring",
|
||||
@ -54,7 +54,7 @@
|
||||
"name": "luci-app-crowdsec-dashboard",
|
||||
"version": "0.7.0-r32",
|
||||
"filename": "luci-app-crowdsec-dashboard_0.7.0-r32_all.ipk",
|
||||
"size": 33740,
|
||||
"size": 33739,
|
||||
"category": "security",
|
||||
"icon": "shield",
|
||||
"description": "CrowdSec security monitoring",
|
||||
@ -66,7 +66,7 @@
|
||||
"name": "luci-app-cyberfeed",
|
||||
"version": "0.1.1-r1",
|
||||
"filename": "luci-app-cyberfeed_0.1.1-r1_all.ipk",
|
||||
"size": 12839,
|
||||
"size": 12837,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -78,7 +78,7 @@
|
||||
"name": "luci-app-device-intel",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-device-intel_1.0.0-r1_all.ipk",
|
||||
"size": 10862,
|
||||
"size": 10859,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -102,7 +102,7 @@
|
||||
"name": "luci-app-dns-provider",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-dns-provider_1.0.0-r1_all.ipk",
|
||||
"size": 7127,
|
||||
"size": 7130,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -114,7 +114,7 @@
|
||||
"name": "luci-app-exposure",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "luci-app-exposure_1.0.0-r3_all.ipk",
|
||||
"size": 9838,
|
||||
"size": 9841,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -126,7 +126,7 @@
|
||||
"name": "luci-app-gitea",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "luci-app-gitea_1.0.0-r2_all.ipk",
|
||||
"size": 15299,
|
||||
"size": 15300,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -138,7 +138,7 @@
|
||||
"name": "luci-app-glances",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "luci-app-glances_1.0.0-r2_all.ipk",
|
||||
"size": 6968,
|
||||
"size": 6969,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -162,7 +162,7 @@
|
||||
"name": "luci-app-hexojs",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "luci-app-hexojs_1.0.0-r3_all.ipk",
|
||||
"size": 30311,
|
||||
"size": 30307,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -174,7 +174,7 @@
|
||||
"name": "luci-app-jellyfin",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-jellyfin_1.0.0-r1_all.ipk",
|
||||
"size": 6060,
|
||||
"size": 6061,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -186,7 +186,7 @@
|
||||
"name": "luci-app-jitsi",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-jitsi_1.0.0-r1_all.ipk",
|
||||
"size": 5139,
|
||||
"size": 5134,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -198,7 +198,7 @@
|
||||
"name": "luci-app-ksm-manager",
|
||||
"version": "0.4.0-r2",
|
||||
"filename": "luci-app-ksm-manager_0.4.0-r2_all.ipk",
|
||||
"size": 18724,
|
||||
"size": 18719,
|
||||
"category": "system",
|
||||
"icon": "cpu",
|
||||
"description": "Kernel memory management",
|
||||
@ -210,7 +210,7 @@
|
||||
"name": "luci-app-localai",
|
||||
"version": "0.1.0-r15",
|
||||
"filename": "luci-app-localai_0.1.0-r15_all.ipk",
|
||||
"size": 13181,
|
||||
"size": 13182,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -222,7 +222,7 @@
|
||||
"name": "luci-app-lyrion",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-lyrion_1.0.0-r1_all.ipk",
|
||||
"size": 6727,
|
||||
"size": 6725,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -234,7 +234,7 @@
|
||||
"name": "luci-app-mac-guardian",
|
||||
"version": "0.5.0-r1",
|
||||
"filename": "luci-app-mac-guardian_0.5.0-r1_all.ipk",
|
||||
"size": 6512,
|
||||
"size": 6509,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -270,7 +270,7 @@
|
||||
"name": "luci-app-master-link",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-master-link_1.0.0-r1_all.ipk",
|
||||
"size": 6248,
|
||||
"size": 6245,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -282,7 +282,7 @@
|
||||
"name": "luci-app-media-flow",
|
||||
"version": "0.6.4-r1",
|
||||
"filename": "luci-app-media-flow_0.6.4-r1_all.ipk",
|
||||
"size": 25416,
|
||||
"size": 25418,
|
||||
"category": "media",
|
||||
"icon": "film",
|
||||
"description": "Media streaming",
|
||||
@ -318,7 +318,7 @@
|
||||
"name": "luci-app-mitmproxy",
|
||||
"version": "0.5.0-r2",
|
||||
"filename": "luci-app-mitmproxy_0.5.0-r2_all.ipk",
|
||||
"size": 11152,
|
||||
"size": 11149,
|
||||
"category": "security",
|
||||
"icon": "lock",
|
||||
"description": "HTTPS proxy and traffic inspection",
|
||||
@ -330,7 +330,7 @@
|
||||
"name": "luci-app-mmpm",
|
||||
"version": "0.2.0-r3",
|
||||
"filename": "luci-app-mmpm_0.2.0-r3_all.ipk",
|
||||
"size": 7901,
|
||||
"size": 7899,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -342,7 +342,7 @@
|
||||
"name": "luci-app-mqtt-bridge",
|
||||
"version": "0.4.0-r4",
|
||||
"filename": "luci-app-mqtt-bridge_0.4.0-r4_all.ipk",
|
||||
"size": 22779,
|
||||
"size": 22780,
|
||||
"category": "iot",
|
||||
"icon": "message-square",
|
||||
"description": "MQTT bridge",
|
||||
@ -354,7 +354,7 @@
|
||||
"name": "luci-app-ndpid",
|
||||
"version": "1.1.2-r2",
|
||||
"filename": "luci-app-ndpid_1.1.2-r2_all.ipk",
|
||||
"size": 22653,
|
||||
"size": 22654,
|
||||
"category": "security",
|
||||
"icon": "eye",
|
||||
"description": "Deep packet inspection",
|
||||
@ -366,7 +366,7 @@
|
||||
"name": "luci-app-netdata-dashboard",
|
||||
"version": "0.5.0-r2",
|
||||
"filename": "luci-app-netdata-dashboard_0.5.0-r2_all.ipk",
|
||||
"size": 20488,
|
||||
"size": 20484,
|
||||
"category": "monitoring",
|
||||
"icon": "bar-chart-2",
|
||||
"description": "System monitoring dashboard",
|
||||
@ -378,7 +378,7 @@
|
||||
"name": "luci-app-network-modes",
|
||||
"version": "0.5.0-r3",
|
||||
"filename": "luci-app-network-modes_0.5.0-r3_all.ipk",
|
||||
"size": 54148,
|
||||
"size": 54149,
|
||||
"category": "network",
|
||||
"icon": "wifi",
|
||||
"description": "Network configuration",
|
||||
@ -390,7 +390,7 @@
|
||||
"name": "luci-app-network-tweaks",
|
||||
"version": "1.0.0-r7",
|
||||
"filename": "luci-app-network-tweaks_1.0.0-r7_all.ipk",
|
||||
"size": 14960,
|
||||
"size": 14957,
|
||||
"category": "network",
|
||||
"icon": "wifi",
|
||||
"description": "Network configuration",
|
||||
@ -402,7 +402,7 @@
|
||||
"name": "luci-app-nextcloud",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-nextcloud_1.0.0-r1_all.ipk",
|
||||
"size": 6486,
|
||||
"size": 6489,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -414,7 +414,7 @@
|
||||
"name": "luci-app-ollama",
|
||||
"version": "0.1.0-r1",
|
||||
"filename": "luci-app-ollama_0.1.0-r1_all.ipk",
|
||||
"size": 12355,
|
||||
"size": 12352,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -426,7 +426,7 @@
|
||||
"name": "luci-app-picobrew",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-picobrew_1.0.0-r1_all.ipk",
|
||||
"size": 9458,
|
||||
"size": 9459,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -450,7 +450,7 @@
|
||||
"name": "luci-app-secubox-admin",
|
||||
"version": "1.0.0-r19",
|
||||
"filename": "luci-app-secubox-admin_1.0.0-r19_all.ipk",
|
||||
"size": 57247,
|
||||
"size": 57245,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -462,7 +462,7 @@
|
||||
"name": "luci-app-secubox-crowdsec",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "luci-app-secubox-crowdsec_1.0.0-r3_all.ipk",
|
||||
"size": 13917,
|
||||
"size": 13923,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -474,7 +474,7 @@
|
||||
"name": "luci-app-secubox-netdiag",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-secubox-netdiag_1.0.0-r1_all.ipk",
|
||||
"size": 15308,
|
||||
"size": 15306,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -498,7 +498,7 @@
|
||||
"name": "luci-app-secubox-p2p",
|
||||
"version": "0.1.0-r1",
|
||||
"filename": "luci-app-secubox-p2p_0.1.0-r1_all.ipk",
|
||||
"size": 44085,
|
||||
"size": 44086,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -510,7 +510,7 @@
|
||||
"name": "luci-app-secubox-portal",
|
||||
"version": "0.7.0-r2",
|
||||
"filename": "luci-app-secubox-portal_0.7.0-r2_all.ipk",
|
||||
"size": 24646,
|
||||
"size": 24644,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox system component",
|
||||
@ -534,7 +534,7 @@
|
||||
"name": "luci-app-service-registry",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-service-registry_1.0.0-r1_all.ipk",
|
||||
"size": 39826,
|
||||
"size": 39828,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -546,7 +546,7 @@
|
||||
"name": "luci-app-simplex",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-simplex_1.0.0-r1_all.ipk",
|
||||
"size": 6999,
|
||||
"size": 7000,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -558,7 +558,7 @@
|
||||
"name": "luci-app-streamlit",
|
||||
"version": "1.0.0-r11",
|
||||
"filename": "luci-app-streamlit_1.0.0-r11_all.ipk",
|
||||
"size": 14748,
|
||||
"size": 14749,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -570,7 +570,7 @@
|
||||
"name": "luci-app-system-hub",
|
||||
"version": "0.5.1-r4",
|
||||
"filename": "luci-app-system-hub_0.5.1-r4_all.ipk",
|
||||
"size": 61106,
|
||||
"size": 61105,
|
||||
"category": "system",
|
||||
"icon": "settings",
|
||||
"description": "System management",
|
||||
@ -582,7 +582,7 @@
|
||||
"name": "luci-app-threat-analyst",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "luci-app-threat-analyst_1.0.0-r1_all.ipk",
|
||||
"size": 6951,
|
||||
"size": 9753,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -594,7 +594,7 @@
|
||||
"name": "luci-app-tor-shield",
|
||||
"version": "1.0.0-r10",
|
||||
"filename": "luci-app-tor-shield_1.0.0-r10_all.ipk",
|
||||
"size": 22361,
|
||||
"size": 22362,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -606,7 +606,7 @@
|
||||
"name": "luci-app-traffic-shaper",
|
||||
"version": "0.4.0-r2",
|
||||
"filename": "luci-app-traffic-shaper_0.4.0-r2_all.ipk",
|
||||
"size": 14537,
|
||||
"size": 14535,
|
||||
"category": "network",
|
||||
"icon": "filter",
|
||||
"description": "Traffic shaping and QoS",
|
||||
@ -618,7 +618,7 @@
|
||||
"name": "luci-app-vhost-manager",
|
||||
"version": "0.5.0-r5",
|
||||
"filename": "luci-app-vhost-manager_0.5.0-r5_all.ipk",
|
||||
"size": 26181,
|
||||
"size": 26186,
|
||||
"category": "network",
|
||||
"icon": "server",
|
||||
"description": "Virtual host management",
|
||||
@ -630,7 +630,7 @@
|
||||
"name": "luci-app-wireguard-dashboard",
|
||||
"version": "0.7.0-r5",
|
||||
"filename": "luci-app-wireguard-dashboard_0.7.0-r5_all.ipk",
|
||||
"size": 39609,
|
||||
"size": 39607,
|
||||
"category": "vpn",
|
||||
"icon": "shield",
|
||||
"description": "WireGuard VPN dashboard",
|
||||
@ -642,7 +642,7 @@
|
||||
"name": "luci-app-zigbee2mqtt",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "luci-app-zigbee2mqtt_1.0.0-r2_all.ipk",
|
||||
"size": 6815,
|
||||
"size": 6813,
|
||||
"category": "iot",
|
||||
"icon": "radio",
|
||||
"description": "Zigbee device management",
|
||||
@ -654,7 +654,7 @@
|
||||
"name": "luci-theme-secubox",
|
||||
"version": "0.4.7-r1",
|
||||
"filename": "luci-theme-secubox_0.4.7-r1_all.ipk",
|
||||
"size": 110241,
|
||||
"size": 110239,
|
||||
"category": "theme",
|
||||
"icon": "palette",
|
||||
"description": "LuCI theme",
|
||||
@ -666,7 +666,7 @@
|
||||
"name": "secubox-app",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "secubox-app_1.0.0-r2_all.ipk",
|
||||
"size": 11182,
|
||||
"size": 11184,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -678,7 +678,7 @@
|
||||
"name": "secubox-app-adguardhome",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "secubox-app-adguardhome_1.0.0-r2_all.ipk",
|
||||
"size": 2882,
|
||||
"size": 2880,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -690,7 +690,7 @@
|
||||
"name": "secubox-app-auth-logger",
|
||||
"version": "1.2.2-r1",
|
||||
"filename": "secubox-app-auth-logger_1.2.2-r1_all.ipk",
|
||||
"size": 9375,
|
||||
"size": 9379,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -702,7 +702,7 @@
|
||||
"name": "secubox-app-crowdsec-custom",
|
||||
"version": "1.1.0-r1",
|
||||
"filename": "secubox-app-crowdsec-custom_1.1.0-r1_all.ipk",
|
||||
"size": 5758,
|
||||
"size": 5761,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -714,7 +714,7 @@
|
||||
"name": "secubox-app-cs-firewall-bouncer",
|
||||
"version": "0.0.31-r4_aarch64",
|
||||
"filename": "secubox-app-cs-firewall-bouncer_0.0.31-r4_aarch64_cortex-a72.ipk",
|
||||
"size": 5049326,
|
||||
"size": 5049328,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -726,7 +726,7 @@
|
||||
"name": "secubox-app-cyberfeed",
|
||||
"version": "0.2.1-r1",
|
||||
"filename": "secubox-app-cyberfeed_0.2.1-r1_all.ipk",
|
||||
"size": 12453,
|
||||
"size": 12454,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -738,7 +738,7 @@
|
||||
"name": "secubox-app-device-intel",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-device-intel_1.0.0-r1_all.ipk",
|
||||
"size": 13005,
|
||||
"size": 13004,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -750,7 +750,7 @@
|
||||
"name": "secubox-app-dns-provider",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-dns-provider_1.0.0-r1_all.ipk",
|
||||
"size": 5590,
|
||||
"size": 6702,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -762,7 +762,7 @@
|
||||
"name": "secubox-app-domoticz",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "secubox-app-domoticz_1.0.0-r2_all.ipk",
|
||||
"size": 2546,
|
||||
"size": 2548,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -774,7 +774,7 @@
|
||||
"name": "secubox-app-exposure",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-exposure_1.0.0-r1_all.ipk",
|
||||
"size": 6936,
|
||||
"size": 6934,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -786,7 +786,7 @@
|
||||
"name": "secubox-app-gitea",
|
||||
"version": "1.0.0-r5",
|
||||
"filename": "secubox-app-gitea_1.0.0-r5_all.ipk",
|
||||
"size": 9402,
|
||||
"size": 9407,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -798,7 +798,7 @@
|
||||
"name": "secubox-app-glances",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-glances_1.0.0-r1_all.ipk",
|
||||
"size": 5536,
|
||||
"size": 5538,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -810,7 +810,7 @@
|
||||
"name": "secubox-app-haproxy",
|
||||
"version": "1.0.0-r23",
|
||||
"filename": "secubox-app-haproxy_1.0.0-r23_all.ipk",
|
||||
"size": 15683,
|
||||
"size": 15687,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -822,7 +822,7 @@
|
||||
"name": "secubox-app-hexojs",
|
||||
"version": "1.0.0-r8",
|
||||
"filename": "secubox-app-hexojs_1.0.0-r8_all.ipk",
|
||||
"size": 94937,
|
||||
"size": 94940,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -834,7 +834,7 @@
|
||||
"name": "secubox-app-jellyfin",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-jellyfin_1.0.0-r1_all.ipk",
|
||||
"size": 6182,
|
||||
"size": 6185,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -846,7 +846,7 @@
|
||||
"name": "secubox-app-jitsi",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-jitsi_1.0.0-r1_all.ipk",
|
||||
"size": 8913,
|
||||
"size": 8914,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -858,7 +858,7 @@
|
||||
"name": "secubox-app-localai",
|
||||
"version": "2.25.0-r1",
|
||||
"filename": "secubox-app-localai_2.25.0-r1_all.ipk",
|
||||
"size": 5722,
|
||||
"size": 5720,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -870,7 +870,7 @@
|
||||
"name": "secubox-app-localai-wb",
|
||||
"version": "2.25.0-r1",
|
||||
"filename": "secubox-app-localai-wb_2.25.0-r1_all.ipk",
|
||||
"size": 7953,
|
||||
"size": 7951,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -882,7 +882,7 @@
|
||||
"name": "secubox-app-lyrion",
|
||||
"version": "2.0.2-r1",
|
||||
"filename": "secubox-app-lyrion_2.0.2-r1_all.ipk",
|
||||
"size": 7288,
|
||||
"size": 7287,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -894,7 +894,7 @@
|
||||
"name": "secubox-app-mac-guardian",
|
||||
"version": "0.5.0-r1",
|
||||
"filename": "secubox-app-mac-guardian_0.5.0-r1_all.ipk",
|
||||
"size": 12095,
|
||||
"size": 12099,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -906,7 +906,7 @@
|
||||
"name": "secubox-app-magicmirror2",
|
||||
"version": "0.4.0-r8",
|
||||
"filename": "secubox-app-magicmirror2_0.4.0-r8_all.ipk",
|
||||
"size": 9254,
|
||||
"size": 9253,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -918,7 +918,7 @@
|
||||
"name": "secubox-app-mailinabox",
|
||||
"version": "2.0.0-r1",
|
||||
"filename": "secubox-app-mailinabox_2.0.0-r1_all.ipk",
|
||||
"size": 7571,
|
||||
"size": 7572,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -942,7 +942,7 @@
|
||||
"name": "secubox-app-mitmproxy",
|
||||
"version": "0.5.0-r19",
|
||||
"filename": "secubox-app-mitmproxy_0.5.0-r19_all.ipk",
|
||||
"size": 22954,
|
||||
"size": 22962,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -954,7 +954,7 @@
|
||||
"name": "secubox-app-mmpm",
|
||||
"version": "0.2.0-r5",
|
||||
"filename": "secubox-app-mmpm_0.2.0-r5_all.ipk",
|
||||
"size": 3977,
|
||||
"size": 3975,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -966,7 +966,7 @@
|
||||
"name": "secubox-app-nextcloud",
|
||||
"version": "1.0.0-r2",
|
||||
"filename": "secubox-app-nextcloud_1.0.0-r2_all.ipk",
|
||||
"size": 2955,
|
||||
"size": 2958,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -978,7 +978,7 @@
|
||||
"name": "secubox-app-ollama",
|
||||
"version": "0.1.0-r1",
|
||||
"filename": "secubox-app-ollama_0.1.0-r1_all.ipk",
|
||||
"size": 5736,
|
||||
"size": 5739,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -990,7 +990,7 @@
|
||||
"name": "secubox-app-picobrew",
|
||||
"version": "1.0.0-r7",
|
||||
"filename": "secubox-app-picobrew_1.0.0-r7_all.ipk",
|
||||
"size": 5539,
|
||||
"size": 5540,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -1002,7 +1002,7 @@
|
||||
"name": "secubox-app-simplex",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-simplex_1.0.0-r1_all.ipk",
|
||||
"size": 9233,
|
||||
"size": 9235,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -1026,7 +1026,7 @@
|
||||
"name": "secubox-app-tor",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-app-tor_1.0.0-r1_all.ipk",
|
||||
"size": 7370,
|
||||
"size": 7371,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -1038,7 +1038,7 @@
|
||||
"name": "secubox-app-webapp",
|
||||
"version": "1.5.0-r7",
|
||||
"filename": "secubox-app-webapp_1.5.0-r7_all.ipk",
|
||||
"size": 39173,
|
||||
"size": 39175,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -1050,7 +1050,7 @@
|
||||
"name": "secubox-app-zigbee2mqtt",
|
||||
"version": "1.0.0-r3",
|
||||
"filename": "secubox-app-zigbee2mqtt_1.0.0-r3_all.ipk",
|
||||
"size": 5507,
|
||||
"size": 5510,
|
||||
"category": "secubox",
|
||||
"icon": "package",
|
||||
"description": "SecuBox backend service",
|
||||
@ -1062,7 +1062,7 @@
|
||||
"name": "secubox-core",
|
||||
"version": "0.10.0-r11",
|
||||
"filename": "secubox-core_0.10.0-r11_all.ipk",
|
||||
"size": 87977,
|
||||
"size": 87975,
|
||||
"category": "system",
|
||||
"icon": "box",
|
||||
"description": "SecuBox core components",
|
||||
@ -1074,7 +1074,7 @@
|
||||
"name": "secubox-dns-guard",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-dns-guard_1.0.0-r1_all.ipk",
|
||||
"size": 12476,
|
||||
"size": 12473,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -1086,7 +1086,7 @@
|
||||
"name": "secubox-master-link",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-master-link_1.0.0-r1_all.ipk",
|
||||
"size": 12453,
|
||||
"size": 12456,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -1098,7 +1098,7 @@
|
||||
"name": "secubox-mcp-server",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-mcp-server_1.0.0-r1_all.ipk",
|
||||
"size": 11430,
|
||||
"size": 11431,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -1110,7 +1110,7 @@
|
||||
"name": "secubox-p2p",
|
||||
"version": "0.6.0-r3",
|
||||
"filename": "secubox-p2p_0.6.0-r3_all.ipk",
|
||||
"size": 47675,
|
||||
"size": 47677,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
@ -1122,7 +1122,7 @@
|
||||
"name": "secubox-threat-analyst",
|
||||
"version": "1.0.0-r1",
|
||||
"filename": "secubox-threat-analyst_1.0.0-r1_all.ipk",
|
||||
"size": 9868,
|
||||
"size": 9867,
|
||||
"category": "utility",
|
||||
"icon": "package",
|
||||
"description": "SecuBox package",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user