Skip to content

Commit dc4917a

Browse files
authored
Add files via upload
Added the complete CoD4X Web RCON Tool v1.0.0: - First-time installer (install.php) - Secure authentication system with roles - Multi-server support (servers.json) - Logs viewer with server-friendly scope labels - Bans manager with JSON-backed storage - Fully redesigned topbar with logo - UI alignment fixes + hover states on buttons - Footer branding (Created by Sachael © 2025) - MIT License, README, CHANGELOG, .gitignore
1 parent 6ec5ffd commit dc4917a

File tree

17 files changed

+920
-3
lines changed

17 files changed

+920
-3
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Changelog
2+
3+
## v1.0.0 – First Public GitHub Release
4+
5+
- Cleaned up bans page UI and website‑managed ban storage (`config/bans.json`).
6+
- Ensured tempban / ban buttons use `tempBanClient` and `banClient` for CoD4x.
7+
- Added per‑server logs under `rcon_logs/servers/<serverId>/...` when using saved servers.
8+
- Centralized user auth in `config/auth.php` with JSON‑backed users and roles.
9+
- Added `.gitignore` to keep local config and runtime logs out of version control.
10+
- Added example config files in `config/*.json.example` for safer deployment.
11+
- Added MIT license.

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2025 SachaelHD
3+
Copyright (c) 2025 Dylan Baxter
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 180 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,180 @@
1-
# cod4x-web-rcon-tool
2-
A modern, lightweight PHP web tool for managing Call of Duty 4x servers (CoD4X). Includes RCON command control, player management, bans, logs, multi-server support, first-time installer, secure auth, and clean UI.
1+
# CoD4X Web RCON Tool
2+
3+
A lightweight, single-folder PHP RCON web tool for Call of Duty 4x servers.
4+
5+
- Send RCON commands from a browser
6+
- Saved servers (name/IP/port/RCON) with per‑server logs
7+
- Kick / tempban / permaban players via `clientKick`, `tempBanClient`, and `banClient`
8+
- Simple website‑managed ban list backed by `config/bans.json` and mirrored to `rcon_logs/banlist.log`
9+
- Auth system with JSON‑backed users, login throttling, and admin / mod roles
10+
11+
> **Status:** First public GitHub release (v1.0.0). Tool is designed to be dropped into `/var/www/html/rcon` on a typical Apache + PHP stack.
12+
13+
---
14+
15+
## Features
16+
17+
### RCON Control
18+
- Select a saved server or manually type IP / port / RCON
19+
- Execute any RCON command
20+
- View raw RCON response in the browser
21+
22+
### Player Management
23+
- Kick a player by slot
24+
- Tempban via `tempBanClient <slot> <seconds>`
25+
- Permanent ban via `banClient <slot>`
26+
27+
All actions are logged to `rcon_logs/` (and per‑server subfolders when a saved server is used).
28+
29+
### Logs Tab
30+
- View tail of auth, commands, kicks, tempbans, bans, etc.
31+
- Switch **scope** between:
32+
- **Global logs** (`rcon_logs/*.log`)
33+
- **Per‑server logs** (`rcon_logs/servers/<serverId>/*.log`) when a saved server is selected
34+
35+
### Website Ban List
36+
- Bans page lets you:
37+
- View current website‑managed bans from `config/bans.json`
38+
- Unban by **GUID** or **Ban ID**
39+
- Bans are also mirrored to `rcon_logs/banlist.log` for auditing.
40+
41+
### Users & Roles
42+
- Users stored in `config/users.json`
43+
- Supports:
44+
- **Admins**: full control; can see and edit RCON passwords and server list
45+
- **Moderators**: can use the panel without seeing raw RCON passwords
46+
- Login protection:
47+
- Throttling after too many failures
48+
- Logs login success/failure to `rcon_logs/auth.log`
49+
50+
---
51+
52+
## Requirements
53+
54+
- PHP 7.4+ (no external libraries required)
55+
- Apache or Nginx with PHP‑FPM
56+
- CoD4x server(s) reachable from the webserver
57+
- HTTPS strongly recommended (panel is security‑sensitive)
58+
59+
---
60+
61+
## Installation
62+
63+
1. **Copy files**
64+
65+
```bash
66+
sudo mkdir -p /var/www/html/rcon
67+
sudo cp -r . /var/www/html/rcon
68+
sudo chown -R www-data:www-data /var/www/html/rcon
69+
sudo chmod -R 750 /var/www/html/rcon
70+
```
71+
72+
2. **Config & logs directories**
73+
74+
```bash
75+
sudo -u www-data mkdir -p /var/www/html/rcon/config /var/www/html/rcon/rcon_logs
76+
```
77+
78+
3. **Create real config from examples**
79+
80+
```bash
81+
cd /var/www/html/rcon/config
82+
sudo -u www-data cp users.json.example users.json
83+
sudo -u www-data cp servers.json.example servers.json
84+
sudo -u www-data cp bans.json.example bans.json
85+
86+
sudo chmod 640 /var/www/html/rcon/config/*.json
87+
```
88+
89+
- Default login (first‑run) is:
90+
91+
- **Username:** `admin`
92+
- **Password:** `changeme`
93+
94+
Change this immediately after logging in.
95+
96+
4. **Apache (example)**
97+
98+
Make sure your VirtualHost points to `/var/www/html/rcon` and PHP is enabled. Example:
99+
100+
```apacheconf
101+
<VirtualHost *:80>
102+
ServerName yourpanel.example.com
103+
DocumentRoot /var/www/html/rcon
104+
105+
<Directory /var/www/html/rcon>
106+
AllowOverride All
107+
Require all granted
108+
</Directory>
109+
</VirtualHost>
110+
```
111+
112+
Then:
113+
114+
```bash
115+
sudo a2enmod rewrite
116+
sudo systemctl reload apache2
117+
```
118+
119+
---
120+
121+
## Usage
122+
123+
1. Browse to the panel’s URL (e.g. `http://yourpanel.example.com`).
124+
2. Log in with the admin account.
125+
3. Go to **Users** and update the admin password (and/or create more users).
126+
4. Go to **Servers** and:
127+
- Add each CoD4x server by name, host/IP, port, and RCON password.
128+
5. Use the **Control** tab to:
129+
- Select a saved server
130+
- Send RCON commands
131+
- Kick / tempban / ban players from the live player list
132+
6. Use the **Logs** tab to monitor auth, commands, kicks, and bans.
133+
7. Use the **Bans** tab to manage website‑stored bans.
134+
135+
---
136+
137+
## Security Notes
138+
139+
- **Always use HTTPS** in production.
140+
- Restrict access:
141+
- IP‑whitelist the panel if possible (e.g. only your home/office).
142+
- Or put it behind a VPN.
143+
- Change the default admin password on first login.
144+
- Keep `config/` and `rcon_logs/` owned by the web user (e.g. `www-data`) and not world‑readable.
145+
- Never expose this panel directly to the public internet without additional protections.
146+
147+
---
148+
149+
## Development
150+
151+
This project is intentionally simple:
152+
153+
- No database – all state is JSON (`config/*.json`) and text logs (`rcon_logs/*.log`).
154+
- No frameworks – plain PHP and a single CSS file in `assets/`.
155+
156+
If you want to hack on it:
157+
158+
- Start a PHP built‑in server:
159+
160+
```bash
161+
php -S 127.0.0.1:8080 -t .
162+
```
163+
164+
- Point your browser at `http://127.0.0.1:8080/login.php`.
165+
166+
---
167+
168+
## Roadmap / Ideas
169+
170+
- Optional 2FA for admin accounts
171+
- Per‑user permissions (e.g. ban‑only mods)
172+
- JSON export/import for bans
173+
- Dark theme toggle
174+
- Dockerfile for one‑command deployment
175+
176+
---
177+
178+
## License
179+
180+
Released under the **MIT License**. See [`LICENSE`](LICENSE) for details.

README.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Hotfix: Login reads users.json; settings save hardened
2+
=======================================================
3+
4+
**What’s fixed**
5+
- `login.php` now authenticates against **config/users.json** via `auth_load_users()`
6+
(fallbacks to inline `$USERS` only if JSON doesn’t exist).
7+
- `settings.php` unchanged functionally, but messages improved and save path verified.
8+
9+
**Deploy**
10+
```bash
11+
sudo cp /var/www/html/rcon/login.php /var/www/html/rcon/login.php.bak-$(date +%s) || true
12+
sudo cp /var/www/html/rcon/settings.php /var/www/html/rcon/settings.php.bak-$(date +%s) || true
13+
14+
sudo cp hotfix/login.php /var/www/html/rcon/login.php
15+
sudo cp hotfix/settings.php /var/www/html/rcon/settings.php
16+
sudo chown www-data:www-data /var/www/html/rcon/login.php /var/www/html/rcon/settings.php
17+
sudo chmod 640 /var/www/html/rcon/login.php /var/www/html/rcon/settings.php
18+
```
19+
20+
**Permissions check (only if needed)**
21+
```bash
22+
sudo chown -R www-data:www-data /var/www/html/rcon/config
23+
sudo chmod -R 750 /var/www/html/rcon/config
24+
sudo touch /var/www/html/rcon/config/users.json
25+
sudo chown www-data:www-data /var/www/html/rcon/config/users.json
26+
sudo chmod 640 /var/www/html/rcon/config/users.json
27+
```
28+
29+
Generated 2025-11-12.

assets/styles.css

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* Dark clean theme */
2+
:root{--bg:#0b1220;--card:#0f172a;--ink:#e5e7eb;--muted:#94a3b8;--brand:#38bdf8;--outline:#334155;--danger:#ef4444;--border:#1f2937;--shadow:0 10px 30px rgba(0,0,0,.35)}
3+
*{box-sizing:border-box}
4+
body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial;margin:20px;background:var(--bg);color:var(--ink)}
5+
.container{max-width:1100px;margin:0 auto;background:var(--card);padding:18px;border-radius:14px;box-shadow:var(--shadow);border:1px solid var(--border)}
6+
h2{margin:0}
7+
h3{margin:4px 0 8px 0}
8+
label{display:block;margin-top:12px}
9+
input[type=text],input[type=password],input[type=number],textarea,select{width:100%;padding:10px;border:1px solid var(--outline);border-radius:10px;background:#0b1220;color:var(--ink)}
10+
button{margin-top:12px;padding:10px 14px;border:0;background:var(--brand);color:#0b1220;border-radius:10px;cursor:pointer;font-weight:700}
11+
pre{background:#0b1220;color:#e5e7eb;padding:12px;border-radius:10px;overflow:auto;border:1px solid var(--outline)}
12+
small{color:var(--muted)}
13+
.error{background:#3f1d1e;padding:10px;border-radius:10px;color:#fecaca;margin-top:12px;border:1px solid #7f1d1d}
14+
.flash{background:#0b2a1b;padding:10px;border-radius:10px;color:#b7f0d1;margin-top:12px;border:1px solid #14532d}
15+
.table-wrap{overflow:auto;margin-top:14px}
16+
table{width:100%;border-collapse:collapse;margin-top:8px}
17+
th,td{padding:10px 12px;border-bottom:1px solid var(--outline);text-align:left;white-space:nowrap}
18+
th{background:#0b1220;font-weight:700}
19+
.name{max-width:320px;overflow:hidden;text-overflow:ellipsis}
20+
.actions{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
21+
.actions form{display:inline-flex;margin:0}
22+
.actions button{margin-top:0;padding:8px 10px}
23+
.actions .ban{background:#ef4444;color:#0b1220}
24+
.actions .kick{background:#f59e0b;color:#0b1220}
25+
.section-title{margin-top:22px}
26+
.row{display:grid;grid-template-columns:1fr 1fr;gap:16px}
27+
@media (max-width:800px){.row{grid-template-columns:1fr}}
28+
hr{border:0;border-top:1px solid var(--outline);margin:18px 0}
29+
.tempban-controls{display:inline-flex;gap:8px;align-items:center;flex-wrap:wrap}
30+
.tempban-controls select{width:auto}
31+
.tempban-controls input[type=text]{width:320px;max-width:100%}
32+
.small-note{font-size:.9em;color:var(--muted);margin-top:6px}
33+
.logwarn{background:#2b1f0f;border:1px solid #7c4a03;color:#fcd34d;padding:10px;border-radius:10px;margin-top:10px}
34+
.topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
35+
.linkbtn{background:#0b1220;color:var(--brand);border:1px solid var(--outline);border-radius:10px;padding:8px 12px;text-decoration:none;display:inline-block}
36+
.linkbtn:hover{filter:brightness(1.15)}
37+
.linkbtn.danger{border-color:#7f1d1d;background:#3f1d1e;color:#fecaca}
38+
.tabbar{display:flex;gap:8px;margin-top:8px}
39+
.tab{padding:8px 12px;border-radius:10px;background:#0b1220;text-decoration:none;color:var(--ink);border:1px solid var(--outline)}
40+
.tab.active{background:var(--brand);color:#0b1220;border-color:var(--brand)}
41+
.card{background:#0b1220;border:1px solid var(--outline);padding:12px;border-radius:12px;margin-top:10px}
42+
.controls-inline{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
43+
.controls-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
44+
mark{background:#fde047;color:#0b1220;padding:0 .1em;border-radius:2px}
45+
code{background:#0b1220;padding:2px 6px;border-radius:6px;border:1px solid var(--outline);color:#e5e7eb}
46+
.login-card{max-width:420px;margin:8vh auto;background:#0f172a;padding:22px;border-radius:14px;box-shadow:var(--shadow);border:1px solid var(--outline)}
47+
.login-title{margin:0 0 12px 0}
48+
.filter-inline{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:8px}
49+
.footer{margin-top:18px;font-size:12px;color:var(--muted);text-align:center;opacity:.8}
50+
51+
52+
.topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}
53+
.logo-wrap{display:flex;align-items:center;gap:10px}
54+
.logo-pill{display:inline-flex;align-items:center;justify-content:center;padding:4px 12px;border-radius:999px;background:linear-gradient(135deg,#22d3ee,#6366f1);font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:#e5e7eb;box-shadow:0 4px 12px rgba(15,23,42,.6)}
55+
button,.linkbtn,.kick,.ban{transition:background-color .12s ease,transform .12s ease,box-shadow .12s ease,filter .12s ease}
56+
button:hover,.linkbtn:hover,.kick:hover,.ban:hover{filter:brightness(1.08);transform:translateY(-1px);box-shadow:0 6px 16px rgba(0,0,0,.35)}

config/auth.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
// config/auth.php — users + helpers
3+
4+
ini_set('display_errors','0');
5+
error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
6+
function panel_log_error($msg){ if(is_string($msg)&&$msg!==''){ error_log('RCON Panel: '.$msg); } }
7+
8+
$USERS = [
9+
'admin' => 'PLAINTEXT:changeme',
10+
];
11+
12+
$SITE_NAME = 'CoD4X Web RCON Tool';
13+
$LOGIN_MAX_ATTEMPTS = 8;
14+
$LOGIN_WINDOW_SECONDS = 900;
15+
16+
function _auth_users_json_path(){ return __DIR__ . '/users.json'; }
17+
18+
function auth_load_users(){
19+
$json = _auth_users_json_path();
20+
if (is_file($json)){
21+
$raw = @file_get_contents($json);
22+
if ($raw !== false){
23+
$d = @json_decode($raw, true);
24+
if (is_array($d) && isset($d['users']) && is_array($d['users'])) return $d['users'];
25+
}
26+
}
27+
$res = [];
28+
foreach ($GLOBALS['USERS'] as $u => $h){
29+
$res[$u] = ['hash'=>$h, 'role'=>($u==='admin' ? 'admin' : 'mod')];
30+
}
31+
return $res;
32+
}
33+
34+
function auth_has_persisted_users(){
35+
$json = _auth_users_json_path();
36+
if (!is_file($json)) return false;
37+
$raw = @file_get_contents($json);
38+
if ($raw === false) return false;
39+
$d = @json_decode($raw, true);
40+
if (!is_array($d) || !isset($d['users']) || !is_array($d['users'])) return false;
41+
return count($d['users']) > 0;
42+
}
43+
44+
function auth_save_users($users_assoc, &$error=null){
45+
$json = _auth_users_json_path();
46+
$dir = dirname($json);
47+
if (!is_dir($dir)) {
48+
if (!@mkdir($dir, 0750, true)) { $error = 'Cannot create config dir: '.$dir; return false; }
49+
}
50+
if (!is_writable($dir)) {
51+
@chmod($dir, 0750);
52+
if (!is_writable($dir)) { $error = 'Config dir not writable: '.$dir; return false; }
53+
}
54+
$payload = ['users'=>$users_assoc, 'updated'=>date('c')];
55+
$tmp = $json . '.tmp';
56+
$enc = json_encode($payload, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
57+
if ($enc === false){ $error = 'Failed to encode JSON.'; return false; }
58+
if (@file_put_contents($tmp, $enc, LOCK_EX) === false){ $error='Failed to write temp file'; return false; }
59+
if (!@rename($tmp, $json)){
60+
if (!@copy($tmp, $json) || !@unlink($tmp)){ $error='Failed to move users.json into place'; return false; }
61+
}
62+
@chmod($json, 0640);
63+
return true;
64+
}
65+
66+
function auth_is_admin($username){
67+
$users = auth_load_users();
68+
return isset($users[$username]) && (($users[$username]['role'] ?? 'mod') === 'admin');
69+
}

config/bans.json.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"bans": [],
3+
"updated": "2025-11-13T09:17:14.649232Z"
4+
}

config/servers.json.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"servers": [
3+
{
4+
"id": "example-server-id",
5+
"name": "My CoD4x Server",
6+
"host": "127.0.0.1",
7+
"port": 28960,
8+
"rcon": "changeme"
9+
}
10+
],
11+
"updated": "2025-11-13T09:17:14.648642Z"
12+
}

config/users.json.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"users": {
3+
"admin": {
4+
"hash": "PLAINTEXT:changeme",
5+
"role": "admin"
6+
}
7+
},
8+
"updated": "2025-11-13T09:17:14.647882Z"
9+
}

includes/footer.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
// includes/footer.php — shared footer snippet
3+
if (!function_exists('panel_footer')) {
4+
function panel_footer(){
5+
echo "<div class='footer'>Created by Sachael &copy; 2025 &middot; CoD4X Web RCON Tool v1.0.0</div>";
6+
}
7+
}

0 commit comments

Comments
 (0)