前言

在 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 可以实现快速启动和轻量级的容器,同时保持容器之间的隔离。

参考

https://www.cnblogs.com/sammyliu/p/5760125.html

参考链接备份