linux 限制一个程序申请随机端口的范围
前言
在 linux socket 编程的时候,如果使用随机空闲端口,系统会分配一个 1024-65535 中的空闲端口,如果要限制这个范围,需要对 net.ipv4.ip_local_port_range 进行配置,但是这样会影响其他程序分配端口的范围。
原理
利用 linux 可以对资源进行隔离的特性( 其实docker也是类似原理 ), 将网络做个隔离,配合虚拟网卡做NAT转发。
实现
#!/usr/bin/env bash
# 获取网卡名字,用于后面添加路由
NEW_CARD_NAME=`ip route show | awk '/default via/ {print $5}'`
# 创建一个网络命名空间 用于隔离网络 起名叫 myspace
ip netns add myspace
# 创建 虚拟网卡用于 NAT 并且绑定 veth2 到 myspace 这里用的 41.x 网段 添加 myspace 的 veth2 默认路由到 veth1
ip link add veth1 type veth peer name veth2
ip link set veth2 netns myspace
ip addr add 192.168.41.2/24 dev veth1
ip link set veth1 up
ip netns exec myspace ip addr add 192.168.41.3/24 dev veth2
ip netns exec myspace ip link set veth2 up
ip netns exec myspace ip route add default via 192.168.41.2
# 开启内核网络转发功能
echo 1 > /proc/sys/net/ipv4/ip_forward
sysctl -p
# 根据网卡名字设置 NAT
iptables -t nat -A POSTROUTING -s 192.168.41.0/24 -o ${NEW_CARD_NAME} -j MASQUERADE
iptables -t filter -A FORWARD -i ${NEW_CARD_NAME} -o veth1 -j ACCEPT
iptables -t filter -A FORWARD -o ${NEW_CARD_NAME} -i veth1 -j ACCEPT
# 限制端口范围 在 60000-60200
# 宿主机端口 NAT 到 veth2 所在的 myspace
iptables -t nat -A PREROUTING -p udp --dport 60000:60200 -j DNAT --to-destination 192.168.41.3:60000-60200
ip netns exec myspace /usr/sbin/sysctl -w net.ipv4.ip_local_port_range="60000 60200"
# 执行被限制的程序
ip netns exec myspace 目标程序路径
注意
- 整个过程中 192.168.41.* 网段是虚拟网卡的IP,和宿主机无关,只要不冲突就行,宿主机用什么IP无所谓。
- 端口范围和NAT要一致,例子里面用的是 60000-60200
- 这个网络隔离重启系统以后就没了,要重新做一次
- 其他项也可以隔离,不过作用就不是隔离端口了,具体有什么需求看实际情况。
关于docker (这段来自AI,真伪自辩)
命名空间是 Linux 内核的一个特性,它提供了一种隔离内核资源的手段。Docker 使用命名空间来提供不同方面的隔离,包括但不限于:
PID 命名空间:隔离进程 ID,使得容器内的进程与宿主机及其他容器的进程相互独立。
NET 命名空间:隔离网络设备、IP 地址、端口等,每个容器可以有自己的网络配置。
IPC 命名空间:隔离进程间通信(IPC),使得容器内的进程只能与同一容器内的其他进程通信。
MNT 命名空间:隔离挂载点视图,每个容器可以有自己的文件系统视图。
UTS 命名空间:隔离主机名和域名,每个容器可以有自己的主机名和域名。
USER 命名空间:隔离用户和组 ID,使得容器内的用户和组与宿主机或其他容器的用户和组相隔离。
控制组(Cgroups):
Cgroups 限制、记录、隔离进程组所使用的物理资源(CPU、内存、磁盘 I/O 等)。Docker 使用 cgroups 来限制一个或多个容器的资源使用,如 CPU 时间、内存使用量等,从而确保系统的稳定性和安全性。
Union File Systems:
Docker 使用了联合文件系统(Union File Systems),如 AUFS、OverlayFS 等,来为容器提供文件系统层。这些文件系统允许 Docker 将多个文件系统联合到一个单一的视图下,使得容器看起来拥有自己的文件系统环境,而实际上它们共享了宿主机的内核和某些底层文件系统。通过这种方式,Docker 可以实现快速启动和轻量级的容器,同时保持容器之间的隔离。