{"id":19028114,"url":"https://github.com/ffcactus/network-namespace","last_synced_at":"2026-03-04T14:01:57.415Z","repository":{"id":127618638,"uuid":"199469975","full_name":"ffcactus/network-namespace","owner":"ffcactus","description":null,"archived":false,"fork":false,"pushed_at":"2019-08-06T06:40:22.000Z","size":6,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-02T03:19:05.240Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ffcactus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-07-29T14:34:45.000Z","updated_at":"2019-08-06T06:40:24.000Z","dependencies_parsed_at":"2023-07-09T09:00:41.021Z","dependency_job_id":null,"html_url":"https://github.com/ffcactus/network-namespace","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ffcactus%2Fnetwork-namespace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ffcactus%2Fnetwork-namespace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ffcactus%2Fnetwork-namespace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ffcactus%2Fnetwork-namespace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ffcactus","download_url":"https://codeload.github.com/ffcactus/network-namespace/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240079610,"owners_count":19744720,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T21:09:59.533Z","updated_at":"2026-03-04T14:01:57.360Z","avatar_url":"https://github.com/ffcactus.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Overview\n\n这个项目利用Linux的network namespace功能实现在一台物理机上模拟两个硬件。具体来说，我们假设：\n\n- 有2个服务器，他们有独立的IP地址。\n- 有1个bridge，这2个服务器通过这个bridge与外界的网络通讯。\n\n我们需要创建以下虚拟部件来实现上面的效果：\n- 2个network namespace，用来模拟2个服务器各自所在的网络，它们之间是隔离的。\n- 2个virtual ethernet interface (veth) pair，可以认为一个veth pair是2张网卡和连接2张网卡的物理线。\n- 1个virtual bridge，来模拟bridge。\n  \n## 准备工作\n我们一共会用到3个IP地址，分别用于2个veth和一个bridge。这3个IP地址的网段要相同，但是不要和主机IP在同一个网段上，比如有：\n- host: 192.168.206.130\n- veth1: 192.168.106.101\n- veth2: 192.168.106.102\n- bridge: 192.168.106.103\n同时假设host上能与外界通讯的eth是ens33\n\n## 创建network namespace\n创建我们需要的2个network namespace, 假设它们分别叫simulator1, simulator2。\n```code\nip netns add simulator1\nip netns add simulator2\nip netns list\n```\n我们可以在network namespace里执行各种命令\n```code\nip netns exec \u003cnetns_name\u003e \u003ccommand_to_execute\u003e\n```\n比如\n```code\n[root@localhost baibin]# ip netns exec simulator1 ip address show\n1: lo: \u003cLOOPBACK\u003e mtu 65536 qdisc noop state DOWN group default qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n```\n可见新建的network namespace里的网络只有lookback。\n\n可以使用下面的命令删除network namespace:\n```code\nip netns delete \u003cnetns_name\u003e\n```\n\n## 创建veth\n创建我们需要的2个veth, 假设它们分别叫veth1, veth2。并把veth1在bridge那一端叫做br-veth1,veth2在bridge那一端叫做br-veth2。\n```code\n# Create the two pairs.\nip link add veth1 type veth peer name br-veth1\nip link add veth2 type veth peer name br-veth2\n```\n把这2个veth分别分配给network namespace.\n```code\n# Associate the non `br-` side\n# with the corresponding namespace\nip link set veth1 netns simulator1\nip link set veth2 netns simulator2\n```\n此时，我们再看network namespace里面的网络设备时就会发现有所不同了，新加的veth会出现再其中。\n```code\n[root@localhost baibin]# ip netns exec simulator1 ip address show\n1: lo: \u003cLOOPBACK\u003e mtu 65536 qdisc noop state DOWN group default qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n29: veth1@if28: \u003cBROADCAST,MULTICAST\u003e mtu 1500 qdisc noop state DOWN group default qlen 1000\n    link/ether 8a:fb:cb:6c:36:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 0\n```\n可以看到虽然有了veth但是还没有IP地址，可以通过ip addr add命令添加IP地址。\n```code\n[root@localhost baibin]# ip netns exec simulator1 ip addr add 192.168.106.101/24 dev veth1\n\n[root@localhost baibin]# ip netns exec simulator1 ip addr show\n1: lo: \u003cLOOPBACK\u003e mtu 65536 qdisc noop state DOWN group default qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n29: veth1@if28: \u003cBROADCAST,MULTICAST\u003e mtu 1500 qdisc noop state DOWN group default qlen 1000\n    link/ether 8a:fb:cb:6c:36:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 0\n    inet 192.168.106.101/24 scope global veth1\n       valid_lft forever preferred_lft forever\n\n[root@localhost baibin]# ip netns exec simulator2 ip addr add 192.168.106.102/24 dev veth2\n\n[root@localhost baibin]# ip netns exec simulator2 ip addr show\n1: lo: \u003cLOOPBACK\u003e mtu 65536 qdisc noop state DOWN group default qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n31: veth2@if30: \u003cBROADCAST,MULTICAST\u003e mtu 1500 qdisc noop state DOWN group default qlen 1000\n    link/ether 2e:d2:43:89:b0:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0\n    inet 192.168.106.102/24 scope global veth2\n       valid_lft forever preferred_lft forever\n```\n可以使用下面的命令删除veth：\n```code\nip link delete \u003cveth_name\u003e\n```\n\n## 创建bridge\n创建连接2个network namespace的bridge，假设名叫br1。\n```\nip link add name br1 type bridge\n```\n建好以后，可以把在br1这一测的veth端打开\n```code\nip link set br-veth1 up\nip link set br-veth2 up\n```\n然后把在namespace一侧的veth端也打开\n```code\nip netns exec simulator1 ip link set veth1 up\nip netns exec simulator2 ip link set veth2 up\n```\n接着通过设置veth的master device，将其与bridge连接。\n```code\nip link set br-veth1 master br1\nip link set br-veth2 master br1\n```\n我们可以通过下面的命令来查看bridge是那些interface的master device。\n```code\n[root@localhost baibin]# bridge link show br1\n28: br-veth1 state UP @(null): \u003cBROADCAST,MULTICAST,UP,LOWER_UP\u003e mtu 1500 master br1 state disabled priority 32 cost 2\n30: br-veth2 state UP @(null): \u003cBROADCAST,MULTICAST,UP,LOWER_UP\u003e mtu 1500 master br1 state disabled priority 32 cost 2\n```\n接下来给我们的bridge添加一个IP，这个IP会被记录到host的route table，当与2个veth通讯时可以通过它来路由。\n```code\nip addr add 192.168.106.103/24 brd + dev br1\nip link set br1 up\n```\n我们可以查看以下route\n```code\n[root@localhost baibin]# ip route list\n192.168.106.0/24 dev br1 proto kernel scope link src 192.168.106.103\n```\n也可以发现能ping通2个veth了。\n```code\n[root@localhost baibin]# ping 192.168.106.101\nPING 192.168.106.101 (192.168.106.101) 56(84) bytes of data.\n64 bytes from 192.168.106.101: icmp_seq=1 ttl=64 time=0.050 ms\n64 bytes from 192.168.106.101: icmp_seq=2 ttl=64 time=0.040 ms\n64 bytes from 192.168.106.101: icmp_seq=3 ttl=64 time=0.043 ms\n```\n虽然host能ping通veth，但是从network namespace里却没法ping通host,这是因为network namespace里没有默认的route table，需要添加。让它们都通过bridge的IP。\n```code\n[root@localhost baibin]# ip -all netns exec ip route add default via 192.168.106.103\n\nnetns: simulator2\n\nnetns: simulator1\n\n```\n在这之后，在network namespace之内也可以ping通主机192.168.106.133了。\n```code\n[root@localhost baibin]# ip netns exec simulator1 ip route\ndefault via 192.168.106.103 dev veth1\n192.168.106.0/24 dev veth1 proto kernel scope link src 192.168.106.101\n\n[root@localhost baibin]# ip netns exec simulator1 ping 192.168.206.133\nPING 192.168.106.133 (192.168.106.133) 56(84) bytes of data.\n64 bytes from 192.168.106.133: icmp_seq=1 ttl=64 time=0.044 ms\n64 bytes from 192.168.106.133: icmp_seq=2 ttl=64 time=0.044 ms\n64 bytes from 192.168.106.133: icmp_seq=3 ttl=64 time=0.041 ms\n```\n虽然可以在network namespace内ping通主机，但是没法ping通外界。这是因为返回的包没法route到bridge。我们利用NAT (network address translation)来解决这个问题。\n```code\n# Enable IP-forwarding.\necho 1 \u003e /proc/sys/net/ipv4/ip_forward\niptables --policy FORWARD ACCEPT\n\n# Flush forward rules.\niptables -P FORWARD DROP\niptables -F FORWARD\n \n# Flush nat rules.\niptables -t nat -F\n\niptables -t nat -A POSTROUTING -s 192.168.106.0/24 -o ens33 -j MASQUERADE\n\niptables -A FORWARD -i ens33 -o veth1 -j ACCEPT\niptables -A FORWARD -o ens33 -i veth1 -j ACCEPT\niptables -A FORWARD -i ens33 -o veth2 -j ACCEPT\niptables -A FORWARD -o ens33 -i veth2 -j ACCEPT\n```\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fffcactus%2Fnetwork-namespace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fffcactus%2Fnetwork-namespace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fffcactus%2Fnetwork-namespace/lists"}