mirror of
https://github.com/crivion/laranode.git
synced 2026-09-03 06:24:09 +08:00
firewall: remove laranode-ufw.sh - we do that through Process::run() instead
This commit is contained in:
@@ -13,8 +13,7 @@ class AddUfwDenyRuleAction
|
||||
if ($ruleSpec === '') {
|
||||
throw new RuntimeException('Empty rule spec');
|
||||
}
|
||||
$bin = config('laranode.laranode_bin_path') . '/laranode-ufw.sh';
|
||||
$proc = Process::run(['sudo', $bin, 'deny', $ruleSpec]);
|
||||
$proc = Process::run(['bash', '-lc', 'sudo ufw deny ' . escapeshellarg($ruleSpec)]);
|
||||
if ($proc->failed()) {
|
||||
throw new RuntimeException('UFW deny failed: ' . $proc->errorOutput());
|
||||
}
|
||||
|
||||
@@ -13,8 +13,7 @@ class AddUfwRuleAction
|
||||
if ($ruleSpec === '') {
|
||||
throw new RuntimeException('Empty rule spec');
|
||||
}
|
||||
$bin = config('laranode.laranode_bin_path') . '/laranode-ufw.sh';
|
||||
$proc = Process::run(['sudo', $bin, 'allow', $ruleSpec]);
|
||||
$proc = Process::run(['bash', '-lc', 'sudo ufw allow ' . escapeshellarg($ruleSpec)]);
|
||||
if ($proc->failed()) {
|
||||
throw new RuntimeException('UFW allow failed: ' . $proc->errorOutput());
|
||||
}
|
||||
|
||||
31
app/Actions/Firewall/BuildUfwRuleSpecAction.php
Normal file
31
app/Actions/Firewall/BuildUfwRuleSpecAction.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Firewall;
|
||||
|
||||
class BuildUfwRuleSpecAction
|
||||
{
|
||||
public function execute(string $protocol, string $from, string $to, int $port, ?string $comment = null): string
|
||||
{
|
||||
$protocol = strtolower(trim($protocol));
|
||||
$from = trim($from);
|
||||
$to = trim($to);
|
||||
$port = (int) $port;
|
||||
$comment = trim((string) ($comment ?? ''));
|
||||
|
||||
$parts = [
|
||||
'proto ' . $protocol,
|
||||
'from ' . $from,
|
||||
'to ' . $to,
|
||||
'port ' . $port,
|
||||
];
|
||||
|
||||
$spec = implode(' ', $parts);
|
||||
|
||||
if ($comment !== '') {
|
||||
$commentEscaped = str_replace("'", "\\'", $comment);
|
||||
$spec .= " comment '" . $commentEscaped . "'";
|
||||
}
|
||||
|
||||
return $spec;
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,12 @@ class DeleteUfwRuleAction
|
||||
if ($idOrSpec === '') {
|
||||
throw new RuntimeException('Empty rule id/spec');
|
||||
}
|
||||
$bin = config('laranode.laranode_bin_path') . '/laranode-ufw.sh';
|
||||
$proc = Process::run(['sudo', $bin, 'delete', $idOrSpec]);
|
||||
if (ctype_digit($idOrSpec)) {
|
||||
$cmd = 'yes | sudo ufw delete ' . (int) $idOrSpec;
|
||||
} else {
|
||||
$cmd = 'yes | sudo ufw delete ' . escapeshellarg($idOrSpec);
|
||||
}
|
||||
$proc = Process::run(['bash', '-lc', $cmd]);
|
||||
if ($proc->failed()) {
|
||||
throw new RuntimeException('UFW delete failed: ' . $proc->errorOutput());
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@ class GetUfwRulesAction
|
||||
{
|
||||
public function execute(): array
|
||||
{
|
||||
$bin = config('laranode.laranode_bin_path') . '/laranode-ufw.sh';
|
||||
$proc = Process::run(['sudo', $bin, 'list']);
|
||||
$proc = Process::run(['sudo', 'ufw', 'status', 'numbered']);
|
||||
if ($proc->failed()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -8,11 +8,12 @@ class GetUfwStatusAction
|
||||
{
|
||||
public function execute(): string
|
||||
{
|
||||
$bin = config('laranode.laranode_bin_path') . '/laranode-ufw.sh';
|
||||
$proc = Process::run(['sudo', $bin, 'status']);
|
||||
$proc = Process::run(['sudo', 'ufw', 'status']);
|
||||
if ($proc->failed()) {
|
||||
return 'unknown';
|
||||
}
|
||||
return trim($proc->output());
|
||||
$out = trim($proc->output());
|
||||
$lines = preg_split("/\r?\n/", $out);
|
||||
return trim($lines[0] ?? $out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,12 @@ class ToggleUfwAction
|
||||
{
|
||||
public function execute(bool $enable): string
|
||||
{
|
||||
$bin = config('laranode.laranode_bin_path') . '/laranode-ufw.sh';
|
||||
$cmd = $enable ? 'enable' : 'disable';
|
||||
$proc = Process::run(['sudo', $bin, $cmd]);
|
||||
if ($enable) {
|
||||
$proc = Process::run(['sudo', 'ufw', '--force', 'enable']);
|
||||
} else {
|
||||
// disable may prompt; confirm automatically
|
||||
$proc = Process::run(['bash', '-lc', 'yes | sudo ufw disable']);
|
||||
}
|
||||
if ($proc->failed()) {
|
||||
throw new RuntimeException('UFW toggle failed: ' . $proc->errorOutput());
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ use App\Actions\Firewall\DeleteUfwRuleAction;
|
||||
use App\Actions\Firewall\GetUfwRulesAction;
|
||||
use App\Actions\Firewall\GetUfwStatusAction;
|
||||
use App\Actions\Firewall\ToggleUfwAction;
|
||||
use App\Http\Requests\Firewall\ToggleFirewallRequest;
|
||||
use App\Http\Requests\Firewall\CreateFirewallRuleRequest;
|
||||
use App\Actions\Firewall\BuildUfwRuleSpecAction;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Inertia;
|
||||
@@ -21,79 +24,26 @@ class FirewallController extends Controller
|
||||
return Inertia::render('Firewall/Index', compact('status', 'rules'));
|
||||
}
|
||||
|
||||
public function toggle(Request $request): RedirectResponse
|
||||
public function toggle(ToggleFirewallRequest $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'enabled' => 'required|boolean',
|
||||
]);
|
||||
|
||||
$enable = (bool) $validated['enabled'];
|
||||
$enable = (bool) $request->validated('enabled');
|
||||
(new ToggleUfwAction())->execute($enable);
|
||||
|
||||
session()->flash('success', 'Firewall ' . ($enable ? 'enabled' : 'disabled') . ' successfully.');
|
||||
return redirect()->route('firewall.index');
|
||||
}
|
||||
|
||||
public function store(Request $request): RedirectResponse
|
||||
public function store(CreateFirewallRuleRequest $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'type' => 'required|string|in:allow,deny',
|
||||
'protocol' => 'required|string|in:tcp,udp',
|
||||
'port' => 'required|integer|min:1|max:65535',
|
||||
'ip' => 'required|string', // validated below for any|ip|cidr
|
||||
'to' => 'required|string',
|
||||
'comment' => 'nullable|string|max:150',
|
||||
]);
|
||||
|
||||
$from = trim($validated['ip']);
|
||||
$to = trim($validated['to']);
|
||||
|
||||
|
||||
$isAny = fn(string $v) => strtolower($v) === 'any';
|
||||
$isIp = fn(string $v) => filter_var($v, FILTER_VALIDATE_IP) !== false;
|
||||
$isCidr = fn(string $v) => (bool) preg_match(
|
||||
'/^((25[0-5]|2[0-4]\d|1?\d?\d)(\.(25[0-5]|2[0-4]\d|1?\d?\d)){3})\/(3[0-2]|[12]?\d)$/',
|
||||
$v
|
||||
$validated = $request->validated();
|
||||
$spec = (new BuildUfwRuleSpecAction())->execute(
|
||||
strtolower($validated['protocol']),
|
||||
trim($validated['ip']),
|
||||
trim($validated['to']),
|
||||
(int) $validated['port'],
|
||||
$validated['comment'] ?? ''
|
||||
);
|
||||
|
||||
if (!($isAny($from) || $isIp($from) || $isCidr($from))) {
|
||||
return back()
|
||||
->withErrors(['ip' => 'IP must be "any", a valid IP address, or CIDR range.'])
|
||||
->withInput();
|
||||
}
|
||||
|
||||
if (!($isAny($to) || $isIp($to))) {
|
||||
return back()
|
||||
->withErrors(['to' => 'To must be "any" or a valid IP address.'])
|
||||
->withInput();
|
||||
}
|
||||
|
||||
$proto = strtolower($validated['protocol']);
|
||||
$port = (int) $validated['port'];
|
||||
$comment = trim($validated['comment'] ?? '');
|
||||
|
||||
// Escape comment safely for shell passing
|
||||
$commentEscaped = str_replace("'", "\\'", $comment);
|
||||
|
||||
|
||||
$ruleSpecParts = [
|
||||
'proto ' . $proto,
|
||||
'from ' . $from,
|
||||
'to ' . $to,
|
||||
'port ' . $port,
|
||||
];
|
||||
|
||||
$spec = implode(' ', $ruleSpecParts);
|
||||
|
||||
if ($commentEscaped !== '') {
|
||||
$spec .= " comment '" . $commentEscaped . "'";
|
||||
}
|
||||
|
||||
if (empty(trim($spec))) {
|
||||
throw new \RuntimeException('Empty rule spec — cannot execute UFW.');
|
||||
}
|
||||
|
||||
|
||||
if ($validated['type'] === 'allow') {
|
||||
(new AddUfwRuleAction())->execute($spec);
|
||||
} else {
|
||||
|
||||
44
app/Http/Requests/Firewall/CreateFirewallRuleRequest.php
Normal file
44
app/Http/Requests/Firewall/CreateFirewallRuleRequest.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Firewall;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CreateFirewallRuleRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'type' => ['required', 'string', 'in:allow,deny'],
|
||||
'protocol' => ['required', 'string', 'in:tcp,udp'],
|
||||
'port' => ['required', 'integer', 'min:1', 'max:65535'],
|
||||
'ip' => ['required', 'string'],
|
||||
'to' => ['required', 'string'],
|
||||
'comment' => ['nullable', 'string', 'max:150'],
|
||||
];
|
||||
}
|
||||
|
||||
public function withValidator($validator)
|
||||
{
|
||||
$validator->after(function ($validator) {
|
||||
$ip = strtolower(trim($this->input('ip')));
|
||||
$to = strtolower(trim($this->input('to')));
|
||||
|
||||
$isAny = fn(string $v) => $v === 'any';
|
||||
$isIp = fn(string $v) => filter_var($v, FILTER_VALIDATE_IP) !== false;
|
||||
$isCidr = fn(string $v) => (bool) preg_match('/^((25[0-5]|2[0-4]\\d|1?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|1?\\d?\\d)){3})\\/(3[0-2]|[12]?\\d)$/', $v);
|
||||
|
||||
if (!($isAny($ip) || $isIp($ip) || $isCidr($ip))) {
|
||||
$validator->errors()->add('ip', 'IP must be "any", a valid IP address, or CIDR range.');
|
||||
}
|
||||
if (!($isAny($to) || $isIp($to))) {
|
||||
$validator->errors()->add('to', 'To must be "any" or a valid IP address.');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
20
app/Http/Requests/Firewall/ToggleFirewallRequest.php
Normal file
20
app/Http/Requests/Firewall/ToggleFirewallRequest.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests\Firewall;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ToggleFirewallRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'enabled' => ['required', 'boolean'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -248,6 +248,17 @@ cp /home/laranode_ln/panel/laranode-scripts/templates/laranode-queue-worker.serv
|
||||
cp /home/laranode_ln/panel/laranode-scripts/templates/laranode-reverb.service /etc/systemd/system/laranode-reverb.service
|
||||
|
||||
|
||||
echo -e"\033[34m"
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo "Adding default UFW rules for SSH | HTTP | HTTPS | REVERB WEBSOCKETS"
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo -e "\033[0m"
|
||||
ufw allow 22
|
||||
ufw allow 80
|
||||
ufw allow 443
|
||||
ufw allow 8080
|
||||
|
||||
|
||||
echo -e "\033[34m"
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
echo "Setting permissions"
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cmd=${1:-}
|
||||
arg=${2:-}
|
||||
|
||||
run() {
|
||||
if command -v ufw >/dev/null 2>&1; then
|
||||
ufw "$@"
|
||||
else
|
||||
echo "ufw command not found" >&2
|
||||
exit 127
|
||||
fi
|
||||
}
|
||||
|
||||
case "$cmd" in
|
||||
status)
|
||||
run status | head -n1
|
||||
;;
|
||||
enable)
|
||||
yes | run enable >/dev/null
|
||||
echo "enabled"
|
||||
;;
|
||||
disable)
|
||||
yes | run disable >/dev/null
|
||||
echo "disabled"
|
||||
;;
|
||||
list)
|
||||
run status numbered
|
||||
;;
|
||||
allow)
|
||||
if [ -z "${arg:-}" ]; then
|
||||
echo "rule spec required" >&2
|
||||
exit 2
|
||||
fi
|
||||
run allow "$arg" >/dev/null
|
||||
echo "allowed: $arg"
|
||||
;;
|
||||
deny)
|
||||
if [ -z "${arg:-}" ]; then
|
||||
echo "rule spec required" >&2
|
||||
exit 2
|
||||
fi
|
||||
run deny "$arg" >/dev/null
|
||||
echo "denied: $arg"
|
||||
;;
|
||||
delete)
|
||||
if [ -z "${arg:-}" ]; then
|
||||
echo "rule id/spec required" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ "$arg" =~ ^[0-9]+$ ]]; then
|
||||
yes | run delete "$arg" >/dev/null
|
||||
else
|
||||
yes | run delete "$arg" >/dev/null
|
||||
fi
|
||||
echo "deleted: $arg"
|
||||
;;
|
||||
*)
|
||||
echo "unknown command" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user