WSL2에서 외부네트웍에 브릿지하여 사용하기

WSL2에서 Ubuntu 등을 설치하면 기본적으로는 내부 프라이빗 네트워크망을 사용한다. 즉, 아이피 대역이 아예 다른 서브네트웍 망을 생성하여 사용한다는 얘기.

따라서 ipconfig를 이용하여 할당된 IP를 확인해보면,

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.24.175.35  netmask 255.255.240.0  broadcast 172.24.175.255
        inet6 fe80::215:5dff:fea8:1061  prefixlen 64  scopeid 0x20<link>
        ether 00:15:5d:a8:10:61  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 586 (586.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

와 같이 172.24.175.35 등으로 할당된다.

여러가지 이유로 윈도우에서 접속되어 있는 외부네트웍을 접속하고, 또 외부에서 WSL2 안의 시스템에 접속하고 싶을 때가 있는데, 이때는 WSL2의 Bridge 기능을 사용하면 된다.

먼저 Hyper-V 매니저를 설치하고, 실행한다. Windows 추가 기능 관리자를 사용하여 설치할 수 있다.

설치하고, 재부팅을 완료한 이후에, Hyper-V 매니저를 실행하면, 다음과 같이 보일텐데…

메뉴의 Action > Virtual Switch Manager를 실행한다.

이제 New virtual network switch를 클릭고, 외부 네트웍에 브릿지 해야 하므로 External를 선택한 후, Create Virtual Switch를 클릭한다.

이름은 적당히 입력하고 (나중에 사용해야 하므로 적당히…), Connection Type에서 External Network를 선택하고, 현재 외부망에 연결되어 있는 네트웍카드를 선택한다. (예시의 경우엔, 현재 노트북을 이용하여 무선랜으로 외부망에 접속중이므로, 무선랜카드를 선택하였음.)

Apply를 눌러 적용한다.

자, 이제 현재 사용자의 홈디렉토리에 .wslconfig 파일을 생성하고, 다음과 같이 입력한 후, 저장한다.

[WSL2]
networkingMode = bridged
vmSwitch = New Virtual Switch

vmSwitch의 이름은 아까 전 단계에서 생성했던 Virtual Network Switch 이름을 입력하면 된다.

PowerShell를 관리자 권한으로 실행하여 다음과 같이 WSL2를 아예 종료한다.

PS C:\WINDOWS\system32> .\wsl.exe --shutdown

이제 WSL2를 다시 실행한 다음, ifconfig를 실행해 보면,

~$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.100.193  netmask 255.255.255.0  broadcast 192.168.100.255
        ether 5c:bb:f6:9e:ee:fa  txqueuelen 1000  (Ethernet)
        RX packets 2  bytes 684 (684.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2  bytes 684 (684.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

정상적으로 외부 네트웍망의 아이피를 할당받았음을 알 수 있다.
끝!

WSL2에서 윈도우에 연결된 USB 장치 사용하기

공식적으론 지원하지 않음. 하지만 오픈소스로 개발된 툴을 설치하면 윈도우에 연결된 USB 장치를 WSL2 내부에서 사용 가능.

과정 정리.

일단 WSL2는 설치하였고, 여기에선 Ubuntu 20.04.4 LTS를 설치하였음.

먼저 usbipd (https://github.com/dorssel/usbipd-win) 설치

https://github.com/dorssel/usbipd-win/releases/latest 에서 최신 버전의 설치 파일을 받아서 설치. 설치후 재부팅 필요.

윈도우에서 Power Shell을 관리자 권한으로 실행. 터미널 화면에서,

PS C:\WINDOWS\system32> usbipd wsl list
BUSID  VID:PID    DEVICE                                                        STATE
2-1    27c6:533c  Goodix fingerprint                                            Not attached
2-5    0c45:6a0c  Integrated Webcam                                             Not attached
2-13   10c4:ea60  Silicon Labs CP210x USB to UART Bridge (COM3)                 Not attached
2-14   8087:0026  Intel(R) Wireless Bluetooth(R)                                Not attached
3-2    2188:6533  CalDigit Thunderbolt 3 Audio, USB Input Device                Not attached
4-2    0853:0148  USB Input Device                                              Not attached
4-8    2188:0747  USB Mass Storage Device                                       Not attached
9-1    046d:c539  USB Input Device                                              Not attached
9-2    413c:b080  Dell DA20 Adapter                                             Not attached

와 같이 현재 윈도우PC에 연결된 USB 장치 리스트들이 보임. 오른쪽에는 현재 WSL에 연결되어 있는지 여부가 표시됨.

WSL2의 Ubuntu 20.04를 실행하고, 다음과 같이 usbipd 클라이언트 패키지를 설치한다.

$ sudo apt install linux-tools-virtual hwdata
$ sudo update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 20

이제 다시 파워셀로 돌아가서, 다음과 같이 WSL2에 연결될 디바이스를 attach 해줌.

PS C:\WINDOWS\system32> usbipd wsl attach --busid=2-13

버스아이디 번호는 위 리스트에서 참고.

WSL2의 Ubuntu에서 dmesg로 연결을 확인해보면,

...
[  981.156497] vhci_hcd vhci_hcd.0: pdev(0) rhport(0) sockfd(3)
[  981.157731] vhci_hcd vhci_hcd.0: devid(131085) speed(2) speed_str(full-speed)
[  981.159973] vhci_hcd vhci_hcd.0: Device attached
[  981.438826] vhci_hcd: vhci_device speed not set
[  981.508832] usb 1-1: new full-speed USB device number 3 using vhci_hcd
[  981.588445] vhci_hcd: vhci_device speed not set
[  981.658522] usb 1-1: SetAddress Request (3) to port 0
[  981.730925] usb 1-1: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00
[  981.731956] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  981.732837] usb 1-1: Product: CP2102 USB to UART Bridge Controller
[  981.733628] usb 1-1: Manufacturer: Silicon Labs
[  981.734221] usb 1-1: SerialNumber: 0001
[  981.744934] cp210x 1-1:1.0: cp210x converter detected
[  981.751507] usb 1-1: cp210x converter now attached to ttyUSB0

와 같이 정상적으로 연결되고, /dev에 장치가 생성됨을 볼 수 있음. 연결을 해제하려면 파워쉘에서

PS C:\WINDOWS\system32> usbipd wsl detach --busid=2-13

를 입력하면,

[ 1048.211316] vhci_hcd: connection closed
[ 1048.211480] vhci_hcd: stop threads
[ 1048.212982] vhci_hcd: release socket
[ 1048.213452] vhci_hcd: disconnect device
[ 1048.214003] usb 1-1: USB disconnect, device number 3
[ 1048.214792] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0
[ 1048.215669] cp210x 1-1:1.0: device disconnected

정상적으로 연결 해제.

이제 실제 리눅스 시스템에서와 마찬가지로 장치 사용 가능.

덧.

장치를 attach 하는 도중 다음과 같은 에러가 발생하면,

usbipd: error: WSL kernel is not USBIP capable; update with 'wsl --update'.

위에서 제시한 해결 방법대로, wsl를 업데이트 해주면 됨.

참고링크:

Ubuntu 콘솔모드 부팅시 /dev/ttyUSB0가 저절로 끊기는 현상

Ubuntu를 콘솔모드로 부팅할 경우, USB Serial 장비 중 /dev/ttyUSB0를 사용하는 장치가 저절로 끊기는 현상이 발생함.

부팅 이후 USB 장치를 다시 연결하면 정상적으로 사용할 수 있지만, 부팅시 항상 연결 후 끊기는 현상이 발생하여 커널 메시지를 확인한 결과….

[    3.840033] usbcore: registered new interface driver cp210x
[    3.840041] usbserial: USB Serial support registered for cp210x
[    3.840063] cp210x 3-3.4:1.0: cp210x converter detected
[    3.840244] mei_hdcp 0000:00:16.0-b638ab7e-94e2-4ea2-a552-d1c54b627f04: bound 0000:00:02.0 (ops i915_hdcp_component_ops [i915])
[    3.841142] usb 3-3.4: cp210x converter now attached to ttyUSB0

...

[    4.542479] usb 3-3.4: usbfs: interface 0 claimed by cp210x while 'brltty' sets config #1
[    4.543277] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0
[    4.543298] cp210x 3-3.4:1.0: device disconnected

대략 살펴보면, brltty라는 녀석이 실행되면서 USB 인터페이스 0번을 선점하려고 함. 이로 인해 연결이 끊기는 결과를 보임.

간단히 해결 방법은 brltty라는 녀석을 지우면 됨.

brltty가 하는 역할을 살펴보니, Ubuntu 콘솔모드로 부팅시 시각 장애인을 위해 화면 내용을 읽어주는 braille display라는 장비를 운용하기 위한 프로그램임.

$ sudo apt purge brltty

끝.!

RPi SD 카드 백업

RPi 보드에 SD카드를 삽입하고 작업을 진행한 이후, 특정 상태에서 백업을 해놓으면 추후에 반복되는 작업 시간을 줄일 수 있음.

방법은 사용하는 운영체제에 따라 다름.

Windows

Windows에서는 Win32 Disk Imager 사용을 권장함. 해당 링크에서 프로그램을 다운 받아 원본 SD 카드를 넣고 이미지 파일로 백업. 추후 새로운 SD 카드를 넣고 백업해 놓은 이미지 파일을 이용해 쓰기를 하면 끝.

Ubuntu

ubuntu에서는 터미널에서 dd 명령어를 이용하는게 편함. SD카드를 삽입하고, 마운트 된 파티션을 umount 해준 다음,

$ sudo umount /dev/mmcblk0
$ sudo dd if=/dev/mmcblk0 of=~/backup_sdcard_lrcharger1500w.img bs=1M status=progress

이렇게 하면 파일로 백업, 다시 새로운 카드에 쓰려면,

$ sudo umount /dev/mmcblk0
$ sudo dd if=~/backup_sdcard_lrcharger1500w.img of=/dev/mmcblk0 bs=1M status=progress

끝!

Ubuntu에서 udev를 이용한 장치 관리

udev는 Linux 서브시스템으로 장치 관리를 위해 사용한다.

udev는 udev rules를 이용해 설정이 가능한데, 이를 이용하면 사용자의 입맛에 맞게 장치의 이름 및 초기화 기능을 수행할 수 있다.

udev rules 파일은 /etc/udev/rules.d에 위치하면 된다. 파일 이름의 형식은 00-<udev_rule_name>.rules로 구성되는데, 앞의 두 숫자는 우선 순위를 나타내고 숫자가 낮을수록 먼저 실행된다.

룰 파일 내부에서는 라인별로 실행이 되며, 대략 내용을 살펴보면

KERNEL=="ttyUSB[0-9]*", MODE="0666", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="ttyPIO"
KERNEL=="ttyUSB[0-9]*", MODE="0666", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ENV{ID_USB_INTERFACE_NUM}=="00", SYMLINK+="ttyCHARGER"
KERNEL=="ttyUSB[0-9]*", MODE="0666", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="ttyHMI"
#KERNEL=="ttyUSB[0-9]*", MODE="0666", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ttyCHARGER%E{ID_USB_INTERFACE_NUM}"

와 같다.

자세한 문법은 https://www.thegeekdiary.com/beginners-guide-to-udev-in-linux/를 참고하면 될듯.

팁.

USB 장치의 경우, idProduct, idVendor 등의 번호가 동일한 제품이 존재할 수 있는데, 이때는 ID_USB_INTERFACE_NUM를 사용하면, USB 허브 및 포트에 꼽힌 순서대로 인덱싱 번호를 얻을 수 있다. 이를 이용하면, 해당되는 장치에 대한 설정 가능

KERNEL=="ttyUSB[0-9]*", MODE="0666", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ENV{ID_USB_INTERFACE_NUM}=="01", SYMLINK+="ttyPIO"

끝.