Compare commits
No commits in common. "afa0616c37eb5160a9c3d02818d05d3bd05900c7" and "1cf3e830d3400458686986dcff9f74039da69e7b" have entirely different histories.
afa0616c37
...
1cf3e830d3
21
LICENSE
21
LICENSE
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Sang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
71
README.md
71
README.md
@ -1,71 +0,0 @@
|
||||
# lxc-iptag
|
||||
|
||||
lxc-iptag is a simple script to add ip tags to LXC containers.
|
||||
|
||||

|
||||
|
||||
This script is only a transitional solution for the official UI to support displaying IPs of LXC containers. See [Displaying IP of container in GUI?](https://forum.proxmox.com/threads/displaying-ip-of-container-in-gui.120841/#post-685752)
|
||||
|
||||
> My original intention was to provide a script that is simple enough and easy to review, avoiding introducing too much complexity as much as possible. After all, this script may be replaced by official support in the near future, and shell scripts and tags are certainly not the best solution. Therefore, this script may not consider introducing too much complex logic or requirements.
|
||||
>
|
||||
> Simple scripts allow users to easily modify the script according to their needs with just a little knowledge of Shell scripting. So feel free to fork it. And to save your time, https://github.com/MorsStefan/proxmox-ip2tag is a cool project that supports more features, especially adding iptag support for VMs. You can first check if this project meets your needs.
|
||||
|
||||
## 1. Installation
|
||||
|
||||
```sh
|
||||
curl -sL https://github.com/gitsang/lxc-iptag/raw/main/install.sh | bash
|
||||
```
|
||||
|
||||
This script will:
|
||||
|
||||
- Install script prerequisites
|
||||
- Install the `lxc-iptag` script to `/usr/local/bin/lxc-iptag`
|
||||
- Copy config file to `/usr/local/etc/lxc-iptag.conf`
|
||||
- Add a systemd unit to start the service
|
||||
|
||||
### 1.1 Update
|
||||
|
||||
```sh
|
||||
curl -sSL https://raw.githubusercontent.com/gitsang/lxc-iptag/main/lxc-iptag -o /usr/local/bin/lxc-iptag && chmod +x /usr/local/bin/lxc-iptag
|
||||
systemctl restart lxc-iptag.service
|
||||
```
|
||||
|
||||
This script will only update the `lxc-iptag` executable script
|
||||
|
||||
## 2. Configure
|
||||
|
||||
Open `/usr/local/etc/lxc-iptag.conf` and change the config
|
||||
|
||||
| Option | Example | Description |
|
||||
| ------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| CIDR_LIST | `(192.168.0.0/16 172.16.0.0/12 10.0.0.0/8)` | IP filter list in CIDR format |
|
||||
| LOOP_INTERVAL | `60` | Main loop interval(seconds) |
|
||||
| FW_NET_INTERFACE_CHECK_INTERVAL | `60` | The interval(seconds) for using `ip link` to check lxc status changed (Set -1 to disable this feature) |
|
||||
| LXC_STATUS_CHECK_INTERVAL | `-1` | The interval(seconds) for using `pct list` to check lxc status changed (Set -1 to disable this feature) |
|
||||
| FORCE_UPDATE_INTERVAL | `1800` | The interval(seconds) for force check and update lxc tags |
|
||||
| EXCLUSION_LIST | see [lxc-iptag.conf](./lxc-iptag.conf) | List of container id or ip to exclude from tagging |
|
||||
|
||||
## 3. Uninstall
|
||||
|
||||
```sh
|
||||
# stop lxc-iptag
|
||||
systemctl stop lxc-iptag.service
|
||||
systemctl disable lxc-iptag.service
|
||||
|
||||
# remove lxc-iptag
|
||||
rm -f /lib/systemd/system/lxc-iptag.service
|
||||
rm -f /usr/local/etc/lxc-iptag.conf
|
||||
rm -f /usr/local/bin/lxc-iptag
|
||||
```
|
||||
|
||||
If you want to remove all lxc-iptag related datas (includes all ip tags), run the following command:
|
||||
|
||||
This script will:
|
||||
|
||||
- Stop and disable `lxc-iptag` systemd service
|
||||
- Remove pve all lxc ip tags
|
||||
- Delete all lxc-iptag related systemd unit, config file and script
|
||||
|
||||
```sh
|
||||
curl -sL https://github.com/gitsang/lxc-iptag/raw/main/uninstall.sh | bash
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 64 KiB |
18
install.sh
18
install.sh
@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -xe
|
||||
|
||||
# install prerequisites
|
||||
apt install -y ipcalc
|
||||
|
||||
# install lxc-iptag
|
||||
curl -sSL https://raw.githubusercontent.com/gitsang/lxc-iptag/main/lxc-iptag -o /usr/local/bin/lxc-iptag && chmod +x /usr/local/bin/lxc-iptag
|
||||
curl -sSL https://raw.githubusercontent.com/gitsang/lxc-iptag/main/lxc-iptag.conf -o /usr/local/etc/lxc-iptag.conf
|
||||
|
||||
# configure lxc-iptag systemd
|
||||
curl -sSL https://raw.githubusercontent.com/gitsang/lxc-iptag/main/lxc-iptag.service -o /etc/systemd/system/lxc-iptag.service
|
||||
|
||||
# start lxc-iptag
|
||||
systemctl daemon-reload
|
||||
systemctl enable lxc-iptag.service
|
||||
systemctl start lxc-iptag.service
|
||||
@ -2,20 +2,16 @@
|
||||
|
||||
# =============== CONFIGURATION =============== #
|
||||
|
||||
# The first three are RFC1918 addresses which should be used inside your local network.
|
||||
# The last one is the RFC6598 address pool (CGNAT) used for ISPs to allocate to networks
|
||||
# without allocating all the routers public IP addresses. It has also been used by a lot
|
||||
# of VPN services for their internal addressing (e.g. Tailscale, Netbird).
|
||||
CIDR_LIST=(
|
||||
192.168.0.0/16
|
||||
172.16.0.0/12
|
||||
10.0.0.0/8
|
||||
100.64.0.0/10
|
||||
10.0.0.0/8
|
||||
)
|
||||
LOOP_INTERVAL=60
|
||||
FW_NET_INTERFACE_CHECK_INTERVAL=60
|
||||
LXC_STATUS_CHECK_INTERVAL=-1
|
||||
FORCE_UPDATE_INTERVAL=1800
|
||||
VM_STATUS_CHECK_INTERVAL=60
|
||||
|
||||
if [ -f "/usr/local/etc/lxc-iptag.conf" ]; then
|
||||
# shellcheck source=./lxc-iptag.conf
|
||||
@ -98,6 +94,56 @@ fw_net_interface_changed() {
|
||||
|
||||
# =============== MAIN =============== #
|
||||
|
||||
update_vm_iptags() {
|
||||
vmid_list=$(qm list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
||||
for vmid in ${vmid_list}; do
|
||||
# Check if the VM ID is in the exclusion list
|
||||
if [[ " ${EXCLUSION_LIST[*]} " == *" ${vmid} "* ]]; then
|
||||
echo "Skipping ${vmid} as it is in the exclusion list"
|
||||
continue
|
||||
fi
|
||||
|
||||
last_tagged_ips=()
|
||||
current_valid_ips=()
|
||||
next_tags=()
|
||||
|
||||
# Parse current tags
|
||||
mapfile -t current_tags < <(qm config "${vmid}" | grep tags | awk '{print $2}' | sed 's/;/\n/g')
|
||||
for current_tag in "${current_tags[@]}"; do
|
||||
if is_valid_ipv4 "${current_tag}"; then
|
||||
last_tagged_ips+=("${current_tag}")
|
||||
continue
|
||||
fi
|
||||
next_tags+=("${current_tag}")
|
||||
done
|
||||
|
||||
# Get current IPs
|
||||
current_ips_full=$(qm guest cmd "${vmid}" network-get-interfaces | jq -r '.[] | .["ip-addresses"][]? | ."ip-address"')
|
||||
for ip in ${current_ips_full}; do
|
||||
# Check if the IP is in the exclusion list
|
||||
if [[ " ${EXCLUSION_LIST[*]} " == *" ${ip} "* ]]; then
|
||||
echo "Skipping IP ${ip} for VM ${vmid} as it is in the exclusion list"
|
||||
continue
|
||||
fi
|
||||
|
||||
if is_valid_ipv4 "${ip}" && ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
|
||||
current_valid_ips+=("${ip}")
|
||||
next_tags+=("${ip}")
|
||||
fi
|
||||
done
|
||||
|
||||
# Skip if no ip change
|
||||
if [[ "$(echo "${last_tagged_ips[@]}" | tr ' ' '\n' | sort -u)" == "$(echo "${current_valid_ips[@]}" | tr ' ' '\n' | sort -u)" ]]; then
|
||||
echo "Skipping ${vmid} cause ip no changes"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Set tags
|
||||
echo "Setting ${vmid} tags from ${current_tags[*]} to ${next_tags[*]}"
|
||||
qm set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")"
|
||||
done
|
||||
}
|
||||
|
||||
update_lxc_iptags() {
|
||||
vmid_list=$(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
||||
for vmid in ${vmid_list}; do
|
||||
@ -152,6 +198,7 @@ init() {
|
||||
current_time=$(date +%s)
|
||||
last_lxc_status_check_time=${current_time}
|
||||
last_fw_net_interface_check_time=${current_time}
|
||||
last_vm_status_check_time=${current_time}
|
||||
fw_net_interface_changed
|
||||
last_update_time=0
|
||||
}
|
||||
@ -183,6 +230,16 @@ check() {
|
||||
fi
|
||||
fi
|
||||
|
||||
time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
|
||||
if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
||||
&& [[ "${time_since_last_vm_status_check}" -ge "${VM_STATUS_CHECK_INTERVAL}" ]]; then
|
||||
echo "Checking VM status..."
|
||||
last_vm_status_check_time=${current_time}
|
||||
update_vm_iptags
|
||||
last_update_time=${current_time}
|
||||
return
|
||||
fi
|
||||
|
||||
time_since_last_update=$((current_time - last_update_time))
|
||||
if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
|
||||
echo "Force updating lxc iptags..."
|
||||
15
iptag.conf
Normal file
15
iptag.conf
Normal file
@ -0,0 +1,15 @@
|
||||
# Configuration file for LXC IP tagging
|
||||
|
||||
# List of allowed CIDRs
|
||||
CIDR_LIST=(
|
||||
192.168.0.0/16
|
||||
172.16.0.0/12
|
||||
10.0.0.0/8
|
||||
100.64.0.0/10
|
||||
)
|
||||
|
||||
# Interval settings (in seconds)
|
||||
LOOP_INTERVAL=60
|
||||
FW_NET_INTERFACE_CHECK_INTERVAL=60
|
||||
LXC_STATUS_CHECK_INTERVAL=-1
|
||||
FORCE_UPDATE_INTERVAL=1800
|
||||
168
iptag.ori
Executable file
168
iptag.ori
Executable file
@ -0,0 +1,168 @@
|
||||
#!/bin/bash
|
||||
|
||||
# =============== CONFIGURATION =============== #
|
||||
|
||||
CONFIG_FILE="/opt/lxc-iptag/iptag.conf"
|
||||
|
||||
# Load the configuration file if it exists
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
# shellcheck source=./lxc-iptag.conf
|
||||
source "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Convert IP to integer for comparison
|
||||
ip_to_int() {
|
||||
local ip="${1}"
|
||||
local a b c d
|
||||
|
||||
IFS=. read -r a b c d <<< "${ip}"
|
||||
echo "$((a << 24 | b << 16 | c << 8 | d))"
|
||||
}
|
||||
|
||||
# Check if IP is in CIDR
|
||||
ip_in_cidr() {
|
||||
local ip="${1}"
|
||||
local cidr="${2}"
|
||||
|
||||
ip_int=$(ip_to_int "${ip}")
|
||||
netmask_int=$(ip_to_int "$(ipcalc -b "${cidr}" | grep Broadcast | awk '{print $2}')")
|
||||
masked_ip_int=$(( "${ip_int}" & "${netmask_int}" ))
|
||||
[[ ${ip_int} -eq ${masked_ip_int} ]] && return 0 || return 1
|
||||
}
|
||||
|
||||
# Check if IP is in any CIDRs
|
||||
ip_in_cidrs() {
|
||||
local ip="${1}"
|
||||
local cidrs=()
|
||||
|
||||
mapfile -t cidrs < <(echo "${2}" | tr ' ' '\n')
|
||||
for cidr in "${cidrs[@]}"; do
|
||||
ip_in_cidr "${ip}" "${cidr}" && return 0
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if IP is valid
|
||||
is_valid_ipv4() {
|
||||
local ip=$1
|
||||
local regex="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
|
||||
|
||||
if [[ $ip =~ $regex ]]; then
|
||||
IFS='.' read -r -a parts <<< "$ip"
|
||||
for part in "${parts[@]}"; do
|
||||
if ! [[ $part =~ ^[0-9]+$ ]] || ((part < 0 || part > 255)); then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
lxc_status_changed() {
|
||||
current_lxc_status=$(pct list 2>/dev/null)
|
||||
if [ "${last_lxc_status}" == "${current_lxc_status}" ]; then
|
||||
return 1
|
||||
else
|
||||
last_lxc_status="${current_lxc_status}"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
fw_net_interface_changed() {
|
||||
current_net_interface=$(ifconfig | grep "^fw")
|
||||
if [ "${last_net_interface}" == "${current_net_interface}" ]; then
|
||||
return 1
|
||||
else
|
||||
last_net_interface="${current_net_interface}"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# =============== MAIN =============== #
|
||||
|
||||
update_lxc_iptags() {
|
||||
vmid_list=$(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
||||
for vmid in ${vmid_list}; do
|
||||
last_tagged_ips=()
|
||||
current_valid_ips=()
|
||||
next_tags=()
|
||||
|
||||
# Parse current tags
|
||||
mapfile -t current_tags < <(pct config "${vmid}" | grep tags | awk '{print $2}' | sed 's/;/\n/g')
|
||||
for current_tag in "${current_tags[@]}"; do
|
||||
if is_valid_ipv4 "${current_tag}"; then
|
||||
last_tagged_ips+=("${current_tag}")
|
||||
continue
|
||||
fi
|
||||
next_tags+=("${current_tag}")
|
||||
done
|
||||
|
||||
# Get current IPs
|
||||
current_ips_full=$(lxc-info -n "${vmid}" -i | awk '{print $2}')
|
||||
for ip in ${current_ips_full}; do
|
||||
if is_valid_ipv4 "${ip}" && ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
|
||||
current_valid_ips+=("${ip}")
|
||||
next_tags+=("${ip}")
|
||||
fi
|
||||
done
|
||||
|
||||
# Skip if no ip change
|
||||
if [[ "$(echo "${last_tagged_ips[@]}" | tr ' ' '\n' | sort -u)" == "$(echo "${current_valid_ips[@]}" | tr ' ' '\n' | sort -u)" ]]; then
|
||||
echo "Skipping ${vmid} cause ip no changes"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Set tags
|
||||
echo "Setting ${vmid} tags from ${current_tags[*]} to ${next_tags[*]}"
|
||||
pct set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")"
|
||||
done
|
||||
}
|
||||
|
||||
check() {
|
||||
current_time=$(date +%s)
|
||||
|
||||
time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
|
||||
if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
|
||||
&& [[ "${time_since_last_lxc_status_check}" -ge "${STATUS_CHECK_INTERVAL}" ]]; then
|
||||
echo "Checking lxc status..."
|
||||
last_lxc_status_check_time=${current_time}
|
||||
if lxc_status_changed; then
|
||||
update_lxc_iptags
|
||||
last_update_time=${current_time}
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
|
||||
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
|
||||
&& [[ "${time_since_last_fw_net_interface_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL}" ]]; then
|
||||
echo "Checking fw net interface..."
|
||||
last_fw_net_interface_check_time=${current_time}
|
||||
if fw_net_interface_changed; then
|
||||
update_lxc_iptags
|
||||
last_update_time=${current_time}
|
||||
return
|
||||
fi
|
||||
fi
|
||||
|
||||
time_since_last_update=$((current_time - last_update_time))
|
||||
if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
|
||||
echo "Force updating lxc iptags..."
|
||||
update_lxc_iptags
|
||||
last_update_time=${current_time}
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
# main: Set the IP tags for all LXC containers
|
||||
main() {
|
||||
while true; do
|
||||
check
|
||||
sleep "${LOOP_INTERVAL}"
|
||||
done
|
||||
}
|
||||
|
||||
main
|
||||
@ -1,22 +0,0 @@
|
||||
# The first three are RFC1918 addresses which should be used inside your local network.
|
||||
# The last one is the RFC6598 address pool (CGNAT) used for ISPs to allocate to networks
|
||||
# without allocating all the routers public IP addresses. It has also been used by a lot
|
||||
# of VPN services for their internal addressing (e.g. Tailscale, Netbird).
|
||||
CIDR_LIST=(
|
||||
192.168.0.0/16
|
||||
172.16.0.0/12
|
||||
10.0.0.0/8
|
||||
100.64.0.0/10
|
||||
)
|
||||
LOOP_INTERVAL=60
|
||||
FW_NET_INTERFACE_CHECK_INTERVAL=60
|
||||
LXC_STATUS_CHECK_INTERVAL=-1
|
||||
FORCE_UPDATE_INTERVAL=1800
|
||||
|
||||
# Exclusion list for IPs or container IDs
|
||||
EXCLUSION_LIST=(
|
||||
# Add IPs or container IDs here
|
||||
# Example:
|
||||
# 192.168.1.100
|
||||
# container_id_1
|
||||
)
|
||||
@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=Start lxc-iptag service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/lxc-iptag
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
46
uninstall.sh
46
uninstall.sh
@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -xe
|
||||
|
||||
# stop lxc-iptag
|
||||
systemctl stop lxc-iptag.service
|
||||
systemctl disable lxc-iptag.service
|
||||
|
||||
# clean ip tags
|
||||
is_valid_ipv4() {
|
||||
local ip=$1
|
||||
local regex="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
|
||||
|
||||
if [[ $ip =~ $regex ]]; then
|
||||
IFS='.' read -r -a parts <<< "$ip"
|
||||
for part in "${parts[@]}"; do
|
||||
if ! [[ $part =~ ^[0-9]+$ ]] || ((part < 0 || part > 255)); then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
vmid_list=$(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')
|
||||
for vmid in ${vmid_list}; do
|
||||
next_tags=()
|
||||
|
||||
# Parse current tags
|
||||
mapfile -t current_tags < <(pct config "${vmid}" | grep tags | awk '{print $2}' | sed 's/;/\n/g')
|
||||
for current_tag in "${current_tags[@]}"; do
|
||||
if ! is_valid_ipv4 "${current_tag}"; then
|
||||
next_tags+=("${current_tag}")
|
||||
fi
|
||||
done
|
||||
|
||||
# Set tags
|
||||
echo "Setting ${vmid} tags from ${current_tags[*]} to ${next_tags[*]}"
|
||||
pct set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")"
|
||||
done
|
||||
|
||||
# remove lxc-iptag
|
||||
rm -f /lib/systemd/system/lxc-iptag.service
|
||||
rm -f /usr/local/etc/lxc-iptag.conf
|
||||
rm -f /usr/local/bin/lxc-iptag
|
||||
Loading…
Reference in New Issue
Block a user