UNIX socket that spans two different mount namespaces
The “init” process can establish a communication channel between the parent namespace and the child namespace.
This channel can be based on UNIX sockets or can even use TCP. To create a UNIX socket that spans two different mount namespaces,
you need to first create the child process, then create the UNIX socket, and then isolate the child into a separate mount namespace. But how can we create the process first, and isolate it later? Linux provides unshare()
. This special system call allows a process to isolate itself from the original namespace, instead of having the parent isolate the child in the first place. For example, the following code has the exact same effect as the code previously mentioned in the network namespace section:
af_unix: Allow connecting to sockets in other network namespaces.
unix_find_other(struct net *net,
unix_find_socket_byinode
1、启动server
2、 同一个namespace启动client
3、新的namespace启动
3、chroot
docker export $(docker create nginx) | tar -C rootfs -xvf -
root@ubuntu:~/docker/container# ls config.json rootfs root@ubuntu:~/docker/container# chroot rootfs /bin/bash root@ubuntu:/# ls bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin srv sys tmp usr var root@ubuntu:/# ./client connect: No such file or directory root@ubuntu:/#
root@ubuntu:~/docker/container# unshare --user --mount --ipc --pid --net --uts -r --fork --propagation private bash root@ubuntu:~/docker/container# ls config.json rootfs root@ubuntu:~/docker/container# cd rootfs/ root@ubuntu:~/docker/container/rootfs# ./client connect: No such file or directory root@ubuntu:~/docker/container/rootfs# ls bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin srv sys tmp usr var root@ubuntu:~/docker/container/rootfs#
https://segmentfault.com/a/1190000006913509
采用mount bind
root@ubuntu:~/docker/container# unshare --user --mount --ipc --pid --net --uts -r --fork --propagation private bash root@ubuntu:~/docker/container# mkdir unix_sock root@ubuntu:~/docker/container# ls ~/docker/unix-domain-socket-example bin client.c ipc.h Makefile server.c root@ubuntu:~/docker/container# mount --bind ~/docker/unix-domain-socket-example ./unix_sock root@ubuntu:~/docker/container# ls unix_sock/ bin client.c ipc.h Makefile server.c root@ubuntu:~/docker/container# cd unix_sock/ root@ubuntu:~/docker/container/unix_sock# ls bin client.c ipc.h Makefile server.c root@ubuntu:~/docker/container/unix_sock# cd bin/ root@ubuntu:~/docker/container/unix_sock/bin# ls client server server.sock root@ubuntu:~/docker/container/unix_sock/bin# ./client sent iccExchangeAPDU receive 15 transmit good! root@ubuntu:~/docker/container/unix_sock/bin#
重新建立mount bind
root@ubuntu:~/docker/container# mkdir rootfs/unixsock root@ubuntu:~/docker/container# mount --bind ~/docker/unix-domain-socket-example ./rootfs/unix_sock mount: ./rootfs/unix_sock: mount point does not exist. root@ubuntu:~/docker/container# ls rootfs/unixsock root@ubuntu:~/docker/container# mount --bind ~/docker/unix-domain-socket-example ./rootfs/unixsock/ root@ubuntu:~/docker/container# chroot rootfs /bin/bash root@ubuntu:/# ls bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin srv sys tmp unixsock usr var root@ubuntu:/# cd unixsock/ root@ubuntu:/unixsock# ls Makefile bin client.c ipc.h server.c root@ubuntu:/unixsock# cd bin/ root@ubuntu:/unixsock/bin# ls client server server.sock root@ubuntu:/unixsock/bin# ./client sent iccExchangeAPDU receive 15 transmit good! root@ubuntu:/unixsock/bin# cd .. root@ubuntu:/unixsock# cd .. root@ubuntu:/# ./client connect: No such file or directory root@ubuntu:/# netstat -lpn Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name netstat: /proc/net/tcp: No such file or directory netstat: /proc/net/tcp6: No such file or directory netstat: /proc/net/udp: No such file or directory netstat: /proc/net/udp6: No such file or directory netstat: /proc/net/raw: No such file or directory netstat: /proc/net/raw6: No such file or directory Active UNIX domain sockets (only servers) Proto RefCnt Flags Type State I-Node PID/Program name Path netstat: /proc/net/unix: No such file or directory root@ubuntu:/#
新建挂载点和net namespace
root@ubuntu:~/docker/container# unshare -m -n /bin/bash root@ubuntu:~/docker/container# ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 root@ubuntu:~/docker/container# ls config.json rootfs root@ubuntu:~/docker/container# cd rootfs/ root@ubuntu:~/docker/container/rootfs# ls bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin srv sys tmp unixsock usr var root@ubuntu:~/docker/container/rootfs# ./client connect: No such file or directory root@ubuntu:~/docker/container/rootfs#
原因是没有用绝对路径,改成/var/run/server.sock
root@ubuntu:~/docker/container/rootfs# cp ../../unix-domain-socket-example/bin/client ./
root@ubuntu:~/docker/container/rootfs# ls
bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin srv sys tmp unixsock usr var
root@ubuntu:~/docker/container/rootfs# ./client
sent iccExchangeAPDU
receive 15 transmit good!
^C
root@ubuntu:~/docker/container/rootfs# unshare --user --mount --ipc --pid --net --uts -r --fork --propagation private bash
root@ubuntu:~/docker/container/rootfs# ./client
sent iccExchangeAPDU
receive 15 transmit good!
root@ubuntu:~/docker/container/rootfs# unshare --user --mount --ipc --pid --net --uts -r --fork --propagation private bash root@ubuntu:~/docker/container/rootfs# ./client sent iccExchangeAPDU receive 15 transmit good! ^C root@ubuntu:~/docker/container/rootfs# ./client & [1] 12 root@ubuntu:~/docker/container/rootfs# sent iccExchangeAPDU receive 15 transmit good! root@ubuntu:~/docker/container/rootfs# ps -elf | grep client0 S root 19962 19365 0 80 0 - 1096 pipe_w 17:23 pts/4 00:00:00 grep --color=auto client root@ubuntu:~/docker/container/rootfs# chroot . /bin/bash root@ubuntu:/# ls bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin srv sys tmp unixsock usr var root@ubuntu:/# ps -elf | grep client root@ubuntu:/# mount -t proc /proc mount: /proc: can't find in /etc/fstab. root@ubuntu:/# mount -t proc proc /proc root@ubuntu:/# ps -elf | grep client 12 root 0:00 ./client 22 root 0:00 grep client root@ubuntu:/# kill -9 12 root@ubuntu:/# ps -elf | grep client
server运行在sandbox
sanbox
root@ubuntu:~/docker/container/rootfs# unshare --user --mount --ipc --pid --net --uts -r --fork --propagation private bash root@ubuntu:~/docker/container/rootfs# mount -t proc proc /proc root@ubuntu:~/docker/container/rootfs# ps -elf F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD 4 S root 1 0 0 80 0 - 1400 wait 17:35 pts/4 00:00:00 bash 0 R root 12 1 0 80 0 - 1741 - 17:36 pts/4 00:00:00 ps -elf root@ubuntu:~/docker/container/rootfs# ls bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin server srv sys tmp unixsock usr var root@ubuntu:~/docker/container/rootfs# ./server & [1] 14 root@ubuntu:~/docker/container/rootfs# chroot . /bin/bash
client 发送
root@ubuntu:~/docker/unix-domain-socket-example/bin# ./client sent iccExchangeAPDU receive 15 transmit good!
****************************************sandbox
https://github.com/denehs/unix-domain-socket-example
root@ubuntu:/# ps -elf | grep server 11 root 0:00 ./server 31 root 0:00 ./server 34 root 0:00 grep server root@ubuntu:/# ls / bin boot client dev docker-entrypoint.d docker-entrypoint.sh etc home lib media mnt opt proc root run sbin server srv sys tmp unixsock usr var root@ubuntu:/# ls /var/run/ lock/ mount/ utmp root@ubuntu:/# ls /var/run/ lock mount utmp root@ubuntu:/# netstat -pan | grep server Active Internet connections (servers and established) Active UNIX domain sockets (servers and established) unix 2 [ ] DGRAM 74752739 31/server /var/run/server.sock root@ubuntu:/# ls -al var/run/server.sock ls: cannot access 'var/run/server.sock': No such file or directory root@ubuntu:/#
已经执行chroot了,client再发送一次
从sandbox退出后又有了,但是无法kill
root@ubuntu:~/docker/container/rootfs# ls -al /proc/22442/ns/ total 0 dr-x--x--x 2 root root 0 Nov 20 17:48 . dr-xr-xr-x 9 root root 0 Nov 20 17:44 .. lrwxrwxrwx 1 root root 0 Nov 20 17:48 cgroup -> 'cgroup:[4026531835]' lrwxrwxrwx 1 root root 0 Nov 20 17:48 ipc -> 'ipc:[4026534439]' lrwxrwxrwx 1 root root 0 Nov 20 17:48 mnt -> 'mnt:[4026534437]' lrwxrwxrwx 1 root root 0 Nov 20 17:48 net -> 'net:[4026534442]' lrwxrwxrwx 1 root root 0 Nov 20 17:48 pid -> 'pid:[4026534440]' lrwxrwxrwx 1 root root 0 Nov 20 17:48 pid_for_children -> 'pid:[4026534440]' lrwxrwxrwx 1 root root 0 Nov 20 17:48 user -> 'user:[4026534436]' lrwxrwxrwx 1 root root 0 Nov 20 17:48 uts -> 'uts:[4026534438]' root@ubuntu:~/docker/container/rootfs#
进入 nsenter -t 22442 -p 然后kill
oot@ubuntu:~/docker/container/rootfs# mount -t proc proc /proc root@ubuntu:~/docker/container/rootfs# ps -elf F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD 4 S root 1 0 0 80 0 - 1400 wait 17:30 pts/4 00:00:00 bash 0 S root 11 1 0 80 0 - 450 skb_wa 17:30 pts/4 00:00:00 ./server 4 S root 56 1 0 80 0 - 1100 wait 17:50 pts/4 00:00:00 nsenter -t 22442 -p 0 S root 57 56 0 80 0 - 1662 wait 17:50 pts/4 00:00:00 -bash 0 R root 79 57 0 80 0 - 1741 - 17:51 pts/4 00:00:00 ps -elf root@ubuntu:~/docker/container/rootfs# kill -9 11 root@ubuntu:~/docker/container/rootfs# ps -elf F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD 4 S root 1 0 0 80 0 - 1400 wait 17:30 pts/4 00:00:00 bash 4 S root 56 1 0 80 0 - 1100 wait 17:50 pts/4 00:00:00 nsenter -t 22442 -p 0 S root 57 56 0 80 0 - 1662 wait 17:50 pts/4 00:00:00 -bash 0 R root 80 57 0 80 0 - 1741 - 17:51 pts/4 00:00:00 ps -elf root@ubuntu:~/docker/container/rootfs# exit logout [1]+ Killed ./server root@ubuntu:~/docker/container/rootfs# ps -elf | grep './server' 0 S root 82 1 0 80 0 - 1096 pipe_w 17:52 pts/4 00:00:00 grep --color=auto ./server root@ubuntu:~/docker/container/rootfs#
*************** 先chroot,然后运行server
root@ubuntu:~/docker/unix-domain-socket-example/bin# ./client connect: Connection refused root@ubuntu:~/docker/unix-domain-socket-example/bin# ./client connect: Connection refused root@ubuntu:~/docker/unix-domain-socket-example/bin# ls -al /var/run/server.sock srwxr-xr-x 1 root root 0 Nov 20 17:36 /var/run/server.sock root@ubuntu:~/docker/unix-domain-socket-example/bin#