188 lines
5.0 KiB
Bash
188 lines
5.0 KiB
Bash
#!/usr/bin/env bash
|
||
# -----------------------------------------------------------------
|
||
# Proxmox Add-IPs (LXC + VMs → Tags)
|
||
# -----------------------------------------------------------------
|
||
# © 2021-2025 community-scripts ORG
|
||
# Author: MickLesk (CanbiZ)
|
||
# License: MIT
|
||
# -----------------------------------------------------------------
|
||
|
||
APP="Proxmox Add-IPs"
|
||
FILE_PATH="/usr/local/bin/prx-add-ips"
|
||
CONF_DIR="/opt/prx-add-ips"
|
||
CONF_FILE="$CONF_DIR/prx-add-ips.conf"
|
||
|
||
set -Eeuo pipefail
|
||
|
||
# --- Farben (optional) ---
|
||
YW="\033[33m"
|
||
GN="\033[1;92m"
|
||
RD="\033[01;31m"
|
||
CL="\033[m"
|
||
msg() { [[ "${USE_COLOR:-true}" == "true" ]] && echo -e "$@" || echo -e "$(echo "$@" | sed -E 's/\x1B\[[0-9;]*[JKmsu]//g')"; }
|
||
msg_info() { msg "${YW}➜ $1${CL}"; }
|
||
msg_ok() { msg "${GN}✔ $1${CL}"; }
|
||
msg_error() { msg "${RD}✖ $1${CL}"; }
|
||
|
||
# -----------------------------------------------------------------
|
||
# Installation
|
||
# -----------------------------------------------------------------
|
||
if [[ -f "$FILE_PATH" ]]; then
|
||
msg_info "$APP already installed at $FILE_PATH"
|
||
exit 0
|
||
fi
|
||
|
||
msg_info "Installing dependencies"
|
||
apt-get update -qq
|
||
apt-get install -y jq ipcalc net-tools >/dev/null
|
||
msg_ok "Dependencies installed"
|
||
|
||
mkdir -p "$CONF_DIR"
|
||
|
||
# -----------------------------------------------------------------
|
||
# Config
|
||
# -----------------------------------------------------------------
|
||
if [[ ! -f "$CONF_FILE" ]]; then
|
||
cat <<EOF >"$CONF_FILE"
|
||
# prx-add-ips.conf – configuration for Proxmox Add-IPs
|
||
|
||
# Allowed CIDRs
|
||
CIDR_LIST=(
|
||
192.168.0.0/16
|
||
10.0.0.0/8
|
||
172.16.0.0/12
|
||
)
|
||
|
||
# Main loop interval in seconds
|
||
LOOP_INTERVAL=60
|
||
|
||
# Use colored output? (true/false)
|
||
USE_COLOR=true
|
||
EOF
|
||
msg_ok "Default config written to $CONF_FILE"
|
||
else
|
||
msg_info "Config $CONF_FILE already exists"
|
||
fi
|
||
|
||
# -----------------------------------------------------------------
|
||
# Main Script
|
||
# -----------------------------------------------------------------
|
||
cat <<"EOF" >"$FILE_PATH"
|
||
#!/usr/bin/env bash
|
||
set -Eeuo pipefail
|
||
|
||
CONFIG_FILE="/opt/prx-add-ips/prx-add-ips.conf"
|
||
[[ -f "$CONFIG_FILE" ]] && source "$CONFIG_FILE"
|
||
|
||
YW="\033[33m"; GN="\033[1;92m"; RD="\033[01;31m"; CL="\033[m"
|
||
msg() { [[ "${USE_COLOR:-true}" == "true" ]] && echo -e "$@" || echo -e "$(echo "$@" | sed -E 's/\x1B\[[0-9;]*[JKmsu]//g')"; }
|
||
msg_info() { msg "${YW}➜ $1${CL}"; }
|
||
msg_ok() { msg "${GN}✔ $1${CL}"; }
|
||
msg_error(){ msg "${RD}✖ $1${CL}"; }
|
||
|
||
is_valid_ipv4() {
|
||
local ip=$1
|
||
[[ $ip =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
|
||
for part in ${ip//./ }; do
|
||
((part >= 0 && part <= 255)) || return 1
|
||
done
|
||
return 0
|
||
}
|
||
|
||
ip_in_cidrs() {
|
||
local ip="$1"
|
||
for cidr in "${CIDR_LIST[@]}"; do
|
||
ipcalc -nb "$cidr" "$ip" &>/dev/null && return 0
|
||
done
|
||
return 1
|
||
}
|
||
|
||
set_tags() {
|
||
local vmid="$1" kind="$2"; shift 2
|
||
local ips=("$@")
|
||
|
||
# aktuelle Tags holen
|
||
local existing_tags=()
|
||
mapfile -t existing_tags < <($kind config "$vmid" | awk '/tags:/{$1=""; print}' | tr ';' '\n')
|
||
|
||
local existing_ips=()
|
||
local non_ip_tags=()
|
||
for t in "${existing_tags[@]}"; do
|
||
if is_valid_ipv4 "$t"; then
|
||
existing_ips+=("$t")
|
||
else
|
||
non_ip_tags+=("$t")
|
||
fi
|
||
done
|
||
|
||
local new_tags=("${non_ip_tags[@]}" "${ips[@]}")
|
||
new_tags=($(printf "%s\n" "${new_tags[@]}" | sort -u))
|
||
|
||
if [[ "$(printf "%s\n" "${existing_ips[@]}" | sort -u)" != "$(printf "%s\n" "${ips[@]}" | sort -u)" ]]; then
|
||
msg_info "$kind $vmid → updating tags to ${new_tags[*]}"
|
||
$kind set "$vmid" -tags "$(IFS=';'; echo "${new_tags[*]}")"
|
||
else
|
||
msg_info "$kind $vmid → no IP change"
|
||
fi
|
||
}
|
||
|
||
update_lxc_iptags() {
|
||
for vmid in $(pct list | awk 'NR>1 {print $1}'); do
|
||
local ips=()
|
||
for ip in $(lxc-info -n "$vmid" -iH 2>/dev/null); do
|
||
is_valid_ipv4 "$ip" && ip_in_cidrs "$ip" && ips+=("$ip")
|
||
done
|
||
[[ ${#ips[@]} -gt 0 ]] && set_tags "$vmid" pct "${ips[@]}"
|
||
done
|
||
}
|
||
|
||
update_vm_iptags() {
|
||
for vmid in $(qm list | awk 'NR>1 {print $1}'); do
|
||
if qm agent "$vmid" ping &>/dev/null; then
|
||
local ips=()
|
||
mapfile -t ips < <(qm agent "$vmid" network-get-interfaces \
|
||
| jq -r '.[]?."ip-addresses"[]?."ip-address" | select(test("^[0-9]+\\."))')
|
||
local filtered=()
|
||
for ip in "${ips[@]}"; do
|
||
is_valid_ipv4 "$ip" && ip_in_cidrs "$ip" && filtered+=("$ip")
|
||
done
|
||
[[ ${#filtered[@]} -gt 0 ]] && set_tags "$vmid" qm "${filtered[@]}"
|
||
fi
|
||
done
|
||
}
|
||
|
||
while true; do
|
||
update_lxc_iptags
|
||
update_vm_iptags
|
||
sleep "${LOOP_INTERVAL:-60}"
|
||
done
|
||
EOF
|
||
|
||
chmod +x "$FILE_PATH"
|
||
msg_ok "Main script installed to $FILE_PATH"
|
||
|
||
# -----------------------------------------------------------------
|
||
# Systemd Service
|
||
# -----------------------------------------------------------------
|
||
SERVICE="/etc/systemd/system/prx-add-ips.service"
|
||
if [[ ! -f "$SERVICE" ]]; then
|
||
cat <<EOF >"$SERVICE"
|
||
[Unit]
|
||
Description=Proxmox Add-IPs (LXC + VM)
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStart=$FILE_PATH
|
||
Restart=always
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
msg_ok "Service created"
|
||
fi
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable -q --now prx-add-ips.service
|
||
msg_ok "$APP service started"
|