diff --git a/scripts/proxmox-vpn-install-dev.sh b/scripts/proxmox-vpn-install-dev.sh index 66a8e5d..f409dd1 100644 --- a/scripts/proxmox-vpn-install-dev.sh +++ b/scripts/proxmox-vpn-install-dev.sh @@ -237,9 +237,15 @@ write_vpn_config() { NORD_PASS_B64=$(printf '%s' "$NORD_PASS" | base64 -w0) local VPN_SERVER_LINE="" - [[ -n "$VPN_HOSTNAME" ]] \ - && VPN_SERVER_LINE=" - SERVER_HOSTNAMES=${VPN_HOSTNAME}" \ - || VPN_SERVER_LINE=" - SERVER_COUNTRIES=${VPN_COUNTRY}" + local VPN_CUSTOM_LINE="" + if [[ -n "$VPN_HOSTNAME" ]]; then + # Dedicated-IP: Custom Config direkt mit IP – bypasses Gluetun Hostname-Validierung + VPN_SERVER_LINE=" - VPN_SERVICE_PROVIDER=custom" + VPN_CUSTOM_LINE=" - OPENVPN_CUSTOM_CONFIG=/gluetun/nordvpn-custom.conf" + else + VPN_SERVER_LINE=" - VPN_SERVICE_PROVIDER=nordvpn" + VPN_CUSTOM_LINE=" - SERVER_COUNTRIES=${VPN_COUNTRY}" + fi # Backup pct exec "$SEL_ID" -- bash -c \ @@ -286,11 +292,11 @@ services: devices: - /dev/net/tun:/dev/net/tun environment: - - VPN_SERVICE_PROVIDER=nordvpn +${VPN_SERVER_LINE} - VPN_TYPE=openvpn - OPENVPN_USER=\${OPENVPN_USER} - OPENVPN_PASSWORD=\${OPENVPN_PASSWORD} -${VPN_SERVER_LINE} +${VPN_CUSTOM_LINE} # HTTP-Proxy aktivieren – darüber leitet Freqtrade den Binance-Traffic - HTTPPROXY=on - HTTPPROXY_LOG=off @@ -348,82 +354,70 @@ start_and_verify() { local vpn_ok=false VPN_IP="" - # Bei Hostname-Modus: Server in Gluetun-DB eintragen (Dedicated-IP Support) + # Bei Hostname-Modus: Dedicated-IP via OPENVPN_CUSTOM_CONFIG + # Gluetun validiert Hostnamen gegen eine hardcodierte interne Liste. + # Dedicated-IP-Server (wie de1370) sind dort nie enthalten. + # Lösung: Custom OpenVPN Config direkt mit der aufgelösten IP → bypasses Validierung komplett. if [[ -n "${VPN_HOSTNAME:-}" ]]; then - info "Lade aktuelle Gluetun Server-Datenbank von GitHub..." - - local DB_PATH="/var/lib/docker/volumes/freqtrade_gluetun_data/_data/servers.json" - local SERVERS_URL="https://raw.githubusercontent.com/qdm12/gluetun/refs/heads/master/internal/storage/servers.json" - - # Volume-Verzeichnis anlegen falls noch nicht vorhanden - pct exec "$SEL_ID" -- bash -c "mkdir -p /var/lib/docker/volumes/freqtrade_gluetun_data/_data" 2>/dev/null || true - - # Aktuelle servers.json von GitHub laden (immer aktuell, richtiges Format) - if pct exec "$SEL_ID" -- bash -c \ - "curl -fsSL '${SERVERS_URL}' -o ${DB_PATH} 2>/dev/null"; then - local srv_count - srv_count=$(pct exec "$SEL_ID" -- bash -c \ - "python3 -c \"import json; d=json.load(open('${DB_PATH}')); print(len(d.get('nordvpn',{}).get('servers',[])))\" 2>/dev/null" || echo "?") - success "Server-Datenbank geladen (${srv_count} NordVPN-Server)" - else - warn "GitHub-Download fehlgeschlagen – fahre trotzdem fort" - fi + info "Dedicated-IP Modus: generiere Custom OpenVPN Config für ${VPN_HOSTNAME}..." # IP per DNS auflösen - local server_ip + local server_ip="" server_ip=$(pct exec "$SEL_ID" -- bash -c "getent hosts ${VPN_HOSTNAME} 2>/dev/null | awk '{print \$1}' | head -1" 2>/dev/null || echo "") [[ -z "$server_ip" ]] && server_ip=$(pct exec "$SEL_ID" -- bash -c "nslookup ${VPN_HOSTNAME} 2>/dev/null | awk '/Address:/ && !/#/{print \$2}' | head -1" 2>/dev/null || echo "") - if [[ -z "$server_ip" ]]; then - warn "DNS-Auflösung für ${VPN_HOSTNAME} fehlgeschlagen – Hostname trotzdem versuchen" - else - info "DNS: ${VPN_HOSTNAME} → ${server_ip}" + [[ -z "$server_ip" ]] && error "IP für ${VPN_HOSTNAME} nicht auflösbar. Hostname prüfen!" + info "DNS: ${VPN_HOSTNAME} → ${server_ip}" - # Eintrag mit korrektem Gluetun-Format hinzufügen - # Format: {"vpn":"openvpn","country":"Germany","region":"Europe","city":"Frankfurt", - # "hostname":"de1370.nordvpn.com","tcp":true,"udp":true,"ips":["1.2.3.4"]} - pct exec "$SEL_ID" -- bash -c "python3 << PYEOF -import json, sys, copy - -path = '${DB_PATH}' -hostname = '${VPN_HOSTNAME}' -ip = '${server_ip}' + # Gluetun Volume-Verzeichnis anlegen + pct exec "$SEL_ID" -- bash -c "mkdir -p /var/lib/docker/volumes/freqtrade_gluetun_data/_data" 2>/dev/null || true + # NordVPN Standard-CA herunterladen + local CA_CONTENT + CA_CONTENT=$(curl -fsSL "https://downloads.nordcdn.com/configs/archives/certificates/servers.zip" 2>/dev/null | python3 -c " +import sys, zipfile, io +data = sys.stdin.buffer.read() try: - with open(path) as f: - db = json.load(f) -except Exception as e: - print(f'Lesefehler: {e}'); sys.exit(1) + with zipfile.ZipFile(io.BytesIO(data)) as z: + for name in z.namelist(): + if name.endswith('.ca') or 'ca' in name.lower(): + print(z.read(name).decode()); break +except: pass +" 2>/dev/null || echo "") -servers = db.get('nordvpn', {}).get('servers', []) + # Custom OpenVPN Config generieren + local CONFIG_PATH="/var/lib/docker/volumes/freqtrade_gluetun_data/_data/nordvpn-custom.conf" + pct exec "$SEL_ID" -- bash -c " +cat > ${CONFIG_PATH} << 'OVPNEOF' +client +dev tun +proto ${VPN_PROTO:-udp} +remote ${server_ip} 1194 +resolv-retry infinite +nobind +persist-key +persist-tun +ping 15 +ping-restart 0 +reneg-sec 0 +comp-lzo no +auth SHA512 +cipher AES-256-CBC +pull +fast-io +auth-user-pass /gluetun/credentials.txt +OVPNEOF" -# Bereits vorhanden? -if any(s.get('hostname') == hostname for s in servers): - print(f'Bereits vorhanden: {hostname}') - sys.exit(0) + # Credentials-Datei für OpenVPN schreiben + pct exec "$SEL_ID" -- bash -c " + source ${FT_DIR}/.env 2>/dev/null + printf '%s +%s +' "\$OPENVPN_USER" "\$OPENVPN_PASSWORD" > /var/lib/docker/volumes/freqtrade_gluetun_data/_data/credentials.txt + chmod 600 /var/lib/docker/volumes/freqtrade_gluetun_data/_data/credentials.txt" -# Vorhandenen deutschen OpenVPN-Eintrag als Template klonen (garantiert richtiges Format) -template = next( - (s for s in servers if s.get('country','').lower() == 'germany' - and s.get('vpn') == 'openvpn'), - None -) -if template is None: - template = next((s for s in servers if s.get('vpn') == 'openvpn'), None) -if template is None: - print('Kein Template gefunden'); sys.exit(1) - -entry = copy.deepcopy(template) -entry['hostname'] = hostname -entry['ips'] = [ip] # Format ist immer ips:[] laut GitHub-Quelle - -servers.append(entry) -db['nordvpn']['servers'] = servers -with open(path, 'w') as f: - json.dump(db, f, indent=2) -print(f'Eingetragen: {hostname} ({ip})') -PYEOF" 2>&1 && success "${VPN_HOSTNAME} (${server_ip}) in Gluetun-DB eingetragen" || { warn "DB-Eintrag fehlgeschlagen"; } - fi + success "Custom Config erstellt: ${VPN_HOSTNAME} → ${server_ip}" + CUSTOM_CONFIG_ENABLED=true fi # Protokoll-Reihenfolge: UDP zuerst, dann automatisch TCP