Hi Cedrik,
sadly, I habe a dynamic IPv6 prefix and my ISP (1&1) is not willing to change that.
I looked through the forum and found you mentioning that it might be possible to use the API via a PHP script to add the dynamic prefix to the access list.
I chatgpted my way through the API documentation, but I couldn't figure out how to update the access list. My problem is that I could not find a unique UUID for the access list. When I looked through the caddy file, I noticed that the UUID is always attached to the subdomain, for example "@cff47bd5-bb15-4551-89bc-9eef1b952b06_pagedomainnet"
My first guess is that I use the script to update the caddy config, but I think that's a stupid idea because then I would no longer be able to use the GUI if my understanding is correct.
Here is the script "I" created with the help of ChatGPT, sadly I am not a programmer, but I work in IT, so I am a little bit familiar with scripting (PowerShell).
Github Link
sadly, I habe a dynamic IPv6 prefix and my ISP (1&1) is not willing to change that.
I looked through the forum and found you mentioning that it might be possible to use the API via a PHP script to add the dynamic prefix to the access list.
I chatgpted my way through the API documentation, but I couldn't figure out how to update the access list. My problem is that I could not find a unique UUID for the access list. When I looked through the caddy file, I noticed that the UUID is always attached to the subdomain, for example "@cff47bd5-bb15-4551-89bc-9eef1b952b06_pagedomainnet"
My first guess is that I use the script to update the caddy config, but I think that's a stupid idea because then I would no longer be able to use the GUI if my understanding is correct.
Here is the script "I" created with the help of ChatGPT, sadly I am not a programmer, but I work in IT, so I am a little bit familiar with scripting (PowerShell).
Github Link
Code Select
#!/usr/local/bin/php
<?php
// === Konfiguration ===
$interface = "pppoe0"; // Name des Netzwerkinterfaces
$prefixLength = 64; // Prefix-Länge (z. B. 56)
$accessListUUID = "cff47bd5-bb15-4551-89bc-9eef1b952b06"; // UUID des Access-List-Eintrags
// API-Zugangsdaten
$api_base_url = "https://opnsense.domain.net/api/caddy/"; // Basis-URL
$api_key = "xxx";
$api_secret = "xxx";
// Statische IPv4-Bereiche
$ipv4_allowed = [
"192.168.0.0/16",
"172.16.0.0/12",
"10.0.0.0/8"
];
// === Funktionen ===
function callApi($endpoint, $method = "GET", $data = null) {
global $api_base_url, $api_key, $api_secret;
$url = $api_base_url . $endpoint;
$ch = curl_init($url);
if ($ch === false) {
echo "Fehler bei curl_init(): " . curl_error($ch) . "\n";
return null;
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$headers = [
"Content-Type: application/json",
"X-API-Key: $api_key",
"X-API-Secret: $api_secret"
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
if ($data !== null) {
$jsonData = json_encode($data, JSON_PRETTY_PRINT);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
}
$response = curl_exec($ch);
if ($response === false) {
echo "Fehler beim Curl-Request: " . curl_error($ch) . "\n";
curl_close($ch);
return null;
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode != 200) {
echo "HTTP-Fehler: " . $httpCode . "\n";
echo "Antwort: " . $response . "\n";
curl_close($ch);
return null;
}
curl_close($ch);
$decodedResponse = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
echo "Ungültige JSON-Antwort: " . json_last_error_msg() . "\n";
return null;
}
return $decodedResponse;
}
function getIPv6Address($interface) {
$cmd = "ifconfig " . escapeshellarg($interface) . " | awk '/inet6 / && !/fe80/ && /prefixlen/ {print $2; exit}'";
$ipv6 = trim(shell_exec($cmd));
if (empty($ipv6)) {
echo "Fehler: Keine IPv6-Adresse gefunden oder Befehl fehlgeschlagen.\n";
return false;
}
return $ipv6;
}
function calculateIPv6Prefix($ipv6, $prefixLength) {
$groups = explode(":", $ipv6);
if (count($groups) < 4) {
return false;
}
$g1 = $groups[0];
$g2 = $groups[1];
$g3 = $groups[2];
$g4 = $groups[3];
$g4 = str_pad($g4, 4, "0", STR_PAD_LEFT);
$prefixPart = substr($g4, 0, 2) . "00";
$networkPrefix = "$g1:$g2:$g3:$prefixPart::";
return $networkPrefix;
}
// === Hauptlogik ===
$ipv6_address = getIPv6Address($interface);
if ($ipv6_address === false) {
echo "Fehler: Keine IPv6-Adresse auf Interface $interface gefunden.\n";
exit(1);
}
echo "Gefundene IPv6-Adresse: $ipv6_address\n";
$dynamicPrefix = calculateIPv6Prefix($ipv6_address, $prefixLength);
if ($dynamicPrefix === false) {
echo "Fehler beim Berechnen des IPv6-Netzwerk-Prefix aus $ipv6_address\n";
exit(1);
}
$dynamicPrefixWithCIDR = $dynamicPrefix . "/" . $prefixLength;
echo "Berechneter dynamischer IPv6-Prefix: $dynamicPrefixWithCIDR\n";
$allowedNetworks = array_merge($ipv4_allowed, [$dynamicPrefixWithCIDR]);
$updateData = [
"uuid" => $accessListUUID,
"client_ip" => $allowedNetworks
];
$jsonData = json_encode($updateData, JSON_PRETTY_PRINT);
var_dump($jsonData);
echo "Sende Update an die Access-Liste (UUID: $accessListUUID)...\n";
$updateResponse = callApi("reverseproxy/setAccessList/" . $accessListUUID, "POST", $updateData);
if ($updateResponse === null) {
echo "Fehler beim Aktualisieren der Access-Liste.\n";
exit(1);
}
// Überprüfe die API-Antwort auf Erfolg
if (isset($updateResponse['status']) && $updateResponse['status'] !== 'success') {
echo "Fehlerhafte API-Antwort: " . $updateResponse['message'] . "\n";
var_dump($updateResponse);
exit(1);
}
echo "Access-Liste erfolgreich aktualisiert.\n";
echo "Löse Neukonfiguration von Caddy aus...\n";
$reconfigResponse = callApi("reverseproxy/service/reconfigure", "POST", []);
if ($reconfigResponse === null) {
echo "Fehler beim Auslösen der Neukonfiguration.\n";
exit(1);
}
echo "Caddy wurde erfolgreich neu konfiguriert.\n";
exit(0);
?>