##
## 전체 VM instance 리스트를 보기
## (참고: Shutdown 상태의 VM까지 모두 보여준다.)
##
$ VBoxManage list vms
"MyExampleVM" {e8904c82-aaaa-bbbb-cccc-dddddbcb0f3}
"SejongVM" {e8904c82-aaaa-bbbb-cccc-dddddbcb0f5}
"JeonjoVM" {e8904c82-aaaa-bbbb-cccc-dddddbcb0f7}
$ VBoxManage list vms -l ## 상세 정보를 보기
... 출력 내용 생략 ...
##
## 현재 동작하고 있는 전체 VM instance 리스트를 보기
##
$ VBoxManage list runningvms
"MyExampleVM" {e8904c82-aaaa-bbbb-cccc-dddddbcb0f3}
"SejongVM" {e8904c82-aaaa-bbbb-cccc-dddddbcb0f5}
##
## 특정 VM instance에 대한 상세한 정보를 보기
##
$ VBoxManage showvminfo MyExampleVM
##
## 새로운 VM instance 생성하기
##
$ VBoxManage list ostypes ## VirtualBox가 제공하는 OS Type 목록을 보여준다.
ID: OpenSUSE_64
Description: openSUSE (64-bit)
Family ID: Linux
Family Desc: Linux
64 bit: true
ID: Ubuntu_64
Description: Ubuntu (64-bit)
Family ID: Linux
Family Desc: Linux
64 bit: true
... 이하 생략 ...
$ VBoxManage createvm --name MyNewUbuntuVM --ostype Ubuntu_64 --register
... 출력 내용 생략 ...
##
## VM Properties 설정하기
##
$ VBoxManage modifyvm MyNewUbuntuVM --cpus 2 --memory 2048 --vram 12
##
## Virtual Network Adapter 설정하기
##
$ VBoxManage modifyvm MyNewUbuntuVM --nic1 bridged --bridgeadapter1 eth0
##
## VM instance를 구동하기
##
$ VBoxManage startvm MyNewUbuntuVM
또는
$ VBoxManage startvm MyNewUbuntuVM --type headless ## 화면으로 출력되는게 없도록 VM 구동
##
## VM instance를 강제 종료하기
##
$ VBoxManage controlvm MyNewUbuntuVM poweroff
South Carolina 대학의 'Open Virtual Switch Lab Series' 문서를 바탕으로 내가 실습한 내용을 이곳에 정리함. ( Network namespace 개념부터 차곡차곡 쌓아 올리면서 Open vSwitch Use Case를 설명하기 때문에 공부하는 사람에게 많은 도움이 된다 )
위 그림에 묘사된 것과 같이 Network를 구성하기 위해 아래 명령을 작성했다. (따라해보면 위 그림과 똑같은 Network 만들어진다)
## root namespace에 존재하는 모든 network interface를 조회
$ ip link
## 네임스페이스 my-ns-a, my-ns-b 를 생성
$ ip netns add my-ns-a
$ ip netns add my-ns-b
## Linux kernel에 존재하는 모든 namespace 조회
$ ip netns
my-ns-b
my-ns-a
## 'my-ns-a' 네임스페이스에 존재하는 network interface 조회
$ ip netns exec my-ns-a ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
## 가상 스위치 'sw1'를 생성
$ ovs-vsctl add-br sw1
## root namespace에 존재하는 network interface를 조회
$ ip link
... 중간 생략 ...
47: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 86:3d:02:69:23:4f brd ff:ff:ff:ff:ff:ff
48: sw1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 16:68:07:5d:c0:40 brd ff:ff:ff:ff:ff:ff
## Open vSwitch에 namespace를 연결하기
## 1) veth peer 생성하기
$ ip link add my-ns-a-eth0 type veth peer name sw1-eth1
$ ip link add my-ns-b-eth0 type veth peer name sw1-eth2
$ ip link
... 중간 생략 ...
47: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 86:3d:02:69:23:4f brd ff:ff:ff:ff:ff:ff
48: sw1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 16:68:07:5d:c0:40 brd ff:ff:ff:ff:ff:ff
51: sw1-eth1@my-ns-a-eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether be:01:52:6f:4b:58 brd ff:ff:ff:ff:ff:ff
52: my-ns-a-eth0@sw1-eth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 96:24:a4:bf:78:f3 brd ff:ff:ff:ff:ff:ff
53: sw1-eth2@my-ns-b-eth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 46:d4:ad:57:18:20 brd ff:ff:ff:ff:ff:ff
54: my-ns-b-eth0@sw1-eth2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 2a:78:4d:57:db:37 brd ff:ff:ff:ff:ff:ff
## 2) veth peer를 각각의 namepace에 연결하기 (Attaching to namespaces)
$ ip link set my-ns-a-eth0 netns my-ns-a
$ ip link set my-ns-b-eth0 netns my-ns-b
$ ip netns exec my-ns-a ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
52: my-ns-a-eth0@if51: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 96:24:a4:bf:78:f3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
$ ip netns exec my-ns-b ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
54: my-ns-b-eth0@if53: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 2a:78:4d:57:db:37 brd ff:ff:ff:ff:ff:ff link-netnsid 0
## 3) 가상 스위치 sw1에 veth peer를 연결하기 (Attaching veth peer to switch sw1)
$ ovs-vsctl add-port sw1 sw1-eth1
$ ovs-vsctl show
...
Bridge sw1
Port sw1
Interface sw1
type: internal
Port sw1-eth1
Interface sw1-eth1
...
$ ovs-vsctl add-port sw1 sw1-eth2
$ ovs-vsctl show
...
Bridge sw1
Port sw1
Interface sw1
type: internal
Port sw1-eth2
Interface sw1-eth2
Port sw1-eth1
Interface sw1-eth1
...
## 가상 스위치의 network port를 activate 하기. (Turning up the network port)
$ ip link set sw1-eth1 up
$ ip link set sw1-eth2 up
$ ip link
...
51: sw1-eth1@if52: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master ovs-system state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
link/ether be:01:52:6f:4b:58 brd ff:ff:ff:ff:ff:ff link-netns my-ns-a
53: sw1-eth2@if54: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master ovs-system state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
link/ether 46:d4:ad:57:18:20 brd ff:ff:ff:ff:ff:ff link-netns my-ns-b
...
## 각각의 namespace에 IP address를 할당하기
$ ip netns exec my-ns-a ip link set dev my-ns-a-eth0 up
$ ip netns exec my-ns-b ip link set dev my-ns-b-eth0 up
$ ip netns exec my-ns-a ip address add 192.168.1.10/24 dev my-ns-a-eth0
$ ip netns exec my-ns-b ip address add 192.168.1.20/24 dev my-ns-b-eth0
## 설정 정보 확인하기
$ ip netns exec my-ns-a ip addr
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
52: my-ns-a-eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 96:24:a4:bf:78:f3 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.1.10/24 scope global my-ns-a-eth0
valid_lft forever preferred_lft forever
inet6 fe80::9424:a4ff:febf:78f3/64 scope link
valid_lft forever preferred_lft forever
$ ip netns exec my-ns-b ip addr
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
54: my-ns-b-eth0@if53: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 2a:78:4d:57:db:37 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.1.20/24 scope global my-ns-b-eth0
valid_lft forever preferred_lft forever
inet6 fe80::2878:4dff:fe57:db37/64 scope link
valid_lft forever preferred_lft forever
## namespace 'my-ns-a'의 routing table 확인하기
$ ip netns exec my-ns-a ip route
192.168.1.0/24 dev my-ns-a-eth0 proto kernel scope link src 192.168.1.10
## namespace 'my-ns-b'의 routing table 확인하기
$ ip netns exec my-ns-b ip route
192.168.1.0/24 dev my-ns-b-eth0 proto kernel scope link src 192.168.1.20
## namespace 'my-ns-a'에서 bash shell 시작하기
$ ip netns exec my-ns-a bash
$ ifconfig
my-ns-a-eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.10 netmask 255.255.255.0 broadcast 0.0.0.0
inet6 fe80::9424:a4ff:febf:78f3 prefixlen 64 scopeid 0x20<link>
ether 96:24:a4:bf:78:f3 txqueuelen 1000 (Ethernet)
RX packets 86 bytes 21517 (21.5 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 13 bytes 1006 (1.0 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
$ ping 192.168.1.20 -c 2
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=1 ttl=64 time=0.088 ms
64 bytes from 192.168.1.20: icmp_seq=2 ttl=64 time=0.079 ms
--- 192.168.1.20 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1007ms
rtt min/avg/max/mdev = 0.079/0.083/0.088/0.004 ms
$ traceroute 192.168.1.20
traceroute to 192.168.1.20 (192.168.1.20), 64 hops max
1 192.168.1.20 0.452ms 0.003ms 0.002ms
##########################################################
## Client Linux OS에서 아래의 명령을 수행
##########################################################
##########################################################
## pptp 관련 패키지를 설치한다.
##########################################################
$ sudo apt install pptp-linux
##########################################################
## /etc/ppp/options 파일을 편집한다.
##########################################################
$ cat /etc/ppp/options
lock
noauth
nobsdcomp
nodeflate
refuse-pap
refuse-eap
refuse-chap
refuse-mschap
mtu 1400
$
##########################################################
## /etc/ppp/chap-secrets 파일을 편집한다.
##########################################################
$ cat /etc/ppp/chap-secrets
sejong PPTP "my-password" *
$
##########################################################
## /etc/ppp/peers/sejong 파일을 편집한다.
##########################################################
$ cat /etc/ppp/peers/sejong
pty "pptp 55.123.12.123 --nolaunchpppd"
name sejong
remotename PPTP
file /etc/ppp/options
ipparam sejong
##########################################################
## << 참고: 이 작업은 필요한 경우만 할 것 !!! >>
##
## 이 내용은 꼭 필요한 것은 아닌데, ppp0 tunnel port가 생성되고 IP address가 설정되고 나서
## static routing table에 추가하고 싶은 내용이 있다면,
## 아래와 같이 ip-up 파일에 route 명령을 추가한다.
## (이렇게 하는 것이 정석적 방법인지는 모르겠다. 일단, 나는 이렇게 사용하고 있다.)
##########################################################
$ cat /etc/ppp/ip-up
... (중간 생략) ...
ip route add 192.168.0.0/24 dev ppp0 # <-- 나는 이 내용을 추가했다.
$
##########################################################
## 이제 설정 작업은 모두 끝났다. pon 명령을 실행하면 잘 동작할 것이다. ^^
##########################################################
##########################################################
## 위에서 설정한 파일을 이용하여 PPTP 서버와 GRE 터널을 만든다.
## 참고로 pon 명령은 "ppp on"을 줄인 말이다.
##########################################################
$ pon sejong debug dump logfd 2 nodetach
...
...
local IP address 192.168.0.220
remote IP address 192.168.0.1
Script /etc/ppp/ip-up started (pid 14290)
Script /etc/ppp/ip-up finished (pid 14290), status = 0x0
참고로, 위 pon 명령을 수행하면 명령행 prompt가 출력되지 않는다. 왜냐하면 pon 명령이 백그라운드로 동작하는 것이 아니기 때문에 pod 명령을 수행한 터미널은 이 상태로 두고, 다른 터미널을 하나 더 열어서 작업해야 한다. 새 터미널에서 아래와 같이 VPN 서버 쪽으로 ping을 보내본다.
$ ping 192.168.0.1
ing 192.168.0.1 -c 1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=4.45 ms
--- 192.168.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 4.448/4.448/4.448/0.000 ms
$
아래의 Network Setting 화면에서 [ VPN ] 항목 옆에 있는 + 버튼을 누르고 VPN Server 정보를 입력하기만 하면 끝이다.
위와 같이 설정하고, VPN 연결을 활성화하는 버튼을 누른다.
그런데 VPN 연결을 몇시간 사용하다보면, 간혹 모르는 사이에 끊어지는 경우가 있다.
그런 경우 아래와 같은 nmcli CLI 명령을 crontab에 추가하고 1시간 간격으로 자동 실행하도록 하면 편하다.
$ nmcli con up id "VPN1"
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/24)
$
알아두면 좋은 명령어 예시
##
## VPN 연결 정보 조회
##
$ nmcli con
NAME UUID TYPE DEVICE
VPN1 b0838d77-ae82-4573-a15b-fba0f8884594 vpn enp4s0
Wired connection 1 bef5ca16-baca-35e4-8259-e5dbbacbe1c0 ethernet enp4s0
$
$ nmcli con down id VPN1