我正在开发一个可以在主机上创建 TUN/TAP 接口的应用程序。我可以使用以下方法创建这样的接口:
sudo ip tuntap add tap0 mode tap
现在的问题是,tap0
这里是硬编码的。它应该是动态的。
当我创建下一个点击设备时,它应该是tap1
等等。
现在,当我继续为设备提供范围时,我可以手动执行以下操作:
sudo ip addr add 172.16.0.1/24 dev tap0
现在当我创建tap1时,我不想重叠ip。
有没有什么简单的方法来管理这些tap设备?
答案1
#!/bin/bash
i=0;
while [ $i -ne 5 ]
do
sudo ip tuntap add tap$i mode tap &>/dev/null
if [[ $? -eq 0 ]]; then
echo "$i"
exit 0
fi
i=$(($i+1))
done
exit 1
尝试 tun0 到 tun4,创建第一个空闲接口并返回编号
答案2
对于下一个可用的点击设备,您可以使用以下功能:
function nextTapDevice() {
counter=-1
while [ $? -eq 0 ]; do
counter=$(($counter+1))
ip link show tap$counter &> /dev/null
done
echo tap$counter
}
nextTapDevice
它的运行原理与 @stony 描述的相同,但它会一直运行直到ip link show
抛出错误。这意味着没有指定的设备tap$counter
可用。该设备名称将是下一个可用的设备名称。
对于下一个可用的 IP 范围,您首先需要遵守策略或 IP 范围。确保此 IP 范围不会与其他应用程序(例如 Docker 等)冲突。
对于我的用例,我决定使用172.16.0.0/16
.我将把最后一个八位字节分配给每个虚拟机(我正在使用的应用程序)。我可以运行 256 个虚拟机。
我将重用nextTapDevice
上面编写的函数的修改版本。tap$counter
我将只返回计数器,而不是在上面的函数中返回。
这是其余的代码:
function nextTapDevice() {
counter=-1
while [ $? -eq 0 ]; do
counter=$(($counter+1))
ip link show tap$counter &> /dev/null
done
echo $counter
}
# nextTapDevice
function nextIPRange() {
for ((i=0; i<$(nextTapDevice);++i)); do
output=$(ip -br addr show tap$i | awk '{print $3}')
done
echo $output | awk -F. '{ print $1"."$2"."$3+1"."$4 }'
}
nextIPRange
缺点:即使在 256 之后,第三个八位字节也会继续递增。如果您的用例超过该点,您可能需要实施额外的检查。
答案3
只是为了好玩,这里有一个 FreeBSD 解决方案,基于 tunN 将使用本地 IP 172.16.N.1 和远程 IP 10.172.N.1 的假设:
#!/usr/bin/env bash
# what's the base name of the network interface? NO SPACES!
devBase='tun'
# Maximum of N interfaces, numbered 0 .. N-1 NO HIGHER THAN 256!
N=256
# what's the printf spec of the tun's local address? NO SPACES!
ipLocal='172.16.%d.1'
# what's the printf spec of the tun's remote address? NO SPACES!
ipRemote='10.172.%d.1'
nextTun() {
# $1 is the device base name
result="$(jot -w "${1}%d" $N 0 | grep -vxFf <(ifconfig -l | grep -ow "${1}[0-9]\+") | head -1)"
if [[ -n "$result" ]]
then
printf '%s\n' "$result"
else
exit $?
fi
}
if tun="$(nextTun $devBase)"
then
devN=${tun#$devBase}
printf 'Creating %s ...\n' "$tun"
ipl=$(printf $ipLocal $devN)
ipr=$(printf $ipRemote $devN)
ifcfg="$(printf 'sudo ifconfig %s create %s %s' "$tun" $ipl $ipr )"
sudo $ifcfg || {
printf '"%s" failed.\n' $tun
exit 2
}
else
printf 'No %s devices available.\n' "$devBase"
exit 1
fi
这声明了一个接受基本接口名称的函数nextTun
,例如tun
.它会快速列出可能的设备jot
列表,删除所有已在使用的设备,并获取第一个(最低的)可用设备。如果没有可用的设备,则该函数不返回任何结果,并返回非零退出代码。N
tun
tun
tun
tun
主要代码测试是否成功nextTun
。如果找到,则它会构造必要的ifconfig
语法来创建具有适当本地和远程 IP 的tun
设备编号。devN
一旦语法被构建,它就会被传递sudo
到执行。如果nextTun
指示分配可用设备失败tun
,则该代码指示没有更多设备可用,并返回非零退出代码。