거의 6년만에 STM32MP 보드를 다시 하나 입수했다(이번에는 STM32MP257F-DK 보드다). 이번 시간 부터는 앞으로 몇차례에 걸쳐서, STM32MP257F-DK 보드 기반 embedded linux와 관련한 다양한 주제를 다뤄 보고자 한다. 이번이 그 일곱번째 시간(마지막)이다. 😎
목차
11. Application 돌려 보기(2) - WireGuard
References
Keywords: STM32MP257F-DK, booting flow, u-boot, linux kernel, device tree, yocto project, Buildroot, STM32CubeIDE, Zephyr RTOS, ROS 2, WireGuard
2026년 4월, 벚꽃이 활짝 피었다~ Time flies like an arrow! 🎯
11. Application 돌려 보기(2) - WireGuard
이번 장에서는 wireguard kernel module과 (필자가 개발하고 있는) wireguard-auto daemon을 STM32MP257F-DK board 에 올리는 과정을 소개해 보고자 한다. 😎
WireGuard와 관련해서는 이미 여러 차례 소개한 바가 있으니, 자세한 사항은 아래 link를 참조해 주기 바란다. 😋
<WireGuard 해부>
<Embedded Linux 상에서의 wireguard>
<Windows용 wireguard>
<Android용 wireguard>
<Wireguard rust project>
------------------------------------------------------------------------
1) WireGuard kernel module 구동하기
먼저, 이절에서는 (yoto project) devtool(자세한 사항은 7장 참조)을 사용하여 linux kernel을 build(kernel config 조정 포함)하는 방법부터 확인해 보도록 하자.
$ DISTRO=openstlinux-weston MACHINE=stm32mp2 source layers/meta-st/scripts/envsetup.sh
Kernel에 대한 recipe명은 virtual/kernel으로 하면 되지만, STM32MP257F-DK board에서 사용하는 구체적인 명칭을 확인하고 싶다면, 아래와 같이 검색을 해보면 된다.
$ devtool search linux-*
...
gobject-introspection Middleware layer between GObject-using C libraries and language bindings
linux-stm32mp Linux STM32MP Kernel
systemtap Script-directed dynamic tracing and performance analysis tool for Linux
linux-stm32mp Linux STM32MP Kernel
systemtap Script-directed dynamic tracing and performance analysis tool for Linux
...
자, 이제 linux-stm32mp라는 kernel recipe 명을 찾았으니, 다음으로 할 일은 devtool modify 명령을 사용하여 linux kernel code를 workspace로 복사(정확히는 git clone을 함)해 오는 것이다.
$ devtool modify -x linux-stm32mp
-> 이렇게 하면, workspace/sources/linux-stm32mp 아래에 kernel source code가 복사된다.
다음으로 kernel menuconfig 창을 띄워, 원하는 대로 config를 조정해 보도록 하자.
$ devtool menuconfig linux-stm32mp
-> 여기에서는 테스트를 위해, WireGuard를 Module 형태로 enable 시켜 보기로 한다.
[그림 11.1.1] kernel menuconfig
[그림 11.1.2] WireGuard Module enable 하기
이렇게 설정 변경한 내용은 workspace/sources/linux-stm32mp/oe-local-files/devtool-fragment.cfg 파일에 저장된다.
[그림 11.1.3] devtool-fragment.cfg 파일
이 상태에서, kernel build를 해 보도록 한다.
-> sources/linux-stm32mp/oe-workdir/build 디렉토리 아래에서 kernel build를 진행한다.
(앞단계의 과정을 거쳐) Kernel build 결과물이 설치되는 위치는 아래와 같다.
$ cd tmp-glibc/deploy/images/stm32mp2/kernel
자, 이제 target board에 앞에서 생성한 kernel image와 modules 파일을 올려 볼 차례이다.
[그림 11.1.4] Target board - STM32MP257F-DK
우선, 다음과 같이 (target board의) ip 주소를 설정한 후,
scp를 사용하여 kernel image 파일과 kernel module 묶음을 target board로 복사하도록 한다.
$ scp ./Image.gz root@192.168.8.227:~/workspace
$ scp ./modules-stripped-stm32mp2.tgz root@192.168.8.227:~/workspace
<Target Board>
Target board로 복사한 내용을 system에 반영한 후, 재부팅하도록 하자.
$ cd workspace
$ cp -f ./Image.gz /boot
$ tar xvzf ./modules-stripped-stm32mp2.tgz -C /
$ sync; sync; reboot
<After reboot>
$ depmod -a
-> depmod는 kernel module에 대한 의존성을 분석한 후, /lib/modules/6.6.116-xxx/modules.dep 파일을 새롭게 갱신시킨다.
-> modprobe 명령은 modules.dep 파일의 내용을 보고, 모듈의 위치를 파악하게 된다.
-> 이 명령 실행 후에는 반드시 reboot을 해 주도록 하자.
$ modprobe wireguard
-> OK, wireguard kernel module이 제대로 올라온다.
[그림 11.1.6] lsmod wireguard
2) yocto project 환경에서 wireguard 구동하기
이번에는 1 절에서 접근한 방법과는 다르게, yocto project layer 내에 wireguard 패키지를 통합시켜 돌려보는 과정을 소개해 보고자 한다.
다행히도, meta-openembedded(meta-networking) layer에는 이미 wireguard kernel module과 wireguard-tools 관련 recipe가 준비되어 있다. 😍
chyi@earth:/mnt/hdd/workspace/ST/STM32MP257K_DK/Distribution-Package/layers/meta-openembedded$ grep -rl wireguard *
meta-networking/recipes-kernel/wireguard/wireguard-module_1.0.20220627.bb
meta-networking/recipes-kernel/wireguard/wireguard.inc
meta-networking/recipes-kernel/wireguard/wireguard-tools_1.0.20210914.bb
meta-networking/conf/layer.conf
meta-networking/recipes-core/packagegroups/packagegroup-meta-networking.bb
meta-oe/recipes-core/sdbus-c++/sdbus-c++-libsystemd/0017-Adjust-for-musl-headers.patch
meta-networking/recipes-kernel/wireguard/wireguard-module_1.0.20220627.bb
meta-networking/recipes-kernel/wireguard/wireguard.inc
meta-networking/recipes-kernel/wireguard/wireguard-tools_1.0.20210914.bb
meta-networking/conf/layer.conf
meta-networking/recipes-core/packagegroups/packagegroup-meta-networking.bb
meta-oe/recipes-core/sdbus-c++/sdbus-c++-libsystemd/0017-Adjust-for-musl-headers.patch
[그림 11.2.1] wireguard-module_1.0.20220627.bb file
[그림 11.2.2] wireguard-tools_1.0.20210914.bb file
따라서, 아래와 같이 두 줄만을 local.conf file에 추가하여 build하면 될 일이다.
$ vi conf/local.conf
...
IMAGE_INSTALL:append = " \
ros-core \
demo-nodes-cpp \
demo-nodes-py \
ros2cli \
ros2run \
ros2topic \
wireguard-tools \
kernel-module-wireguard \
"
ros-core \
demo-nodes-cpp \
demo-nodes-py \
ros2cli \
ros2run \
ros2topic \
wireguard-tools \
kernel-module-wireguard \
"
...
$ bitbake st-image-weston
-> OK, wireguard.ko & wg tool 등이 image에 제대로 통합되었다(build 시간도 오래 걸리지 않는다).
정상 build가 진행되었으니, 1 장에서 소개한 대로, STM32CubeProgrammer를 사용하여 SDcard Image를 다시 설치하도록 한다.
부팅 후, target board에 wireguard가 정상적으로 설치되어 있는지 확인해 본다.
$ sudo minicom -D /dev/ttyACM0
[ 638.676971] wireguard: WireGuard 1.0.0 loaded. See www.wireguard.com for information.
[ 638.679224] wireguard: Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
root@stm32mp2-e3-d2-e5:~# wg -h
Usage: wg <cmd> [<args>]
Available subcommands:
show: Shows the current configuration and device information
showconf: Shows the current configuration of a given WireGuard interface, for use with `setconf'
set: Change the current configuration, add peers, remove peers, or change peers
setconf: Applies a configuration file to a WireGuard interface
addconf: Appends a configuration file to a WireGuard interface
syncconf: Synchronizes a configuration file to a WireGuard interface
genkey: Generates a new private key and writes it to stdout
genpsk: Generates a new preshared key and writes it to stdout
pubkey: Reads a private key from stdin and writes a public key to stdout
You may pass `--help' to any of these subcommands to view usage.
3) wireguard-auto project build 하기
이번 절에서는 필자가 개발하고 있는 wireguard-auto project를 stm32mp257f-dk board 상에서 돌려 보는 내용을 소개해 보고자 한다.
먼저, wireguard-auto project와 관련해서는 아래 link를 참조해 주기 바란다(설계 내용이 상세히 설명되어 있음).
wireguard-auto project 코드는 OpenSTLinux yocto project 개발 환경에서 cross-compile하도록 작업되어 있다.
<Yocto SDK 기반 toolchain 사용하기>
-----------------------------------------------------------------------
$ . /opt/stm32mp2/5.0.15-snapshot/environment-setup-cortexa35-ostl-linux
-> SDK를 사용하기 전에 반드시 이 명령을 실행해 준다.
$ echo $ARCH
arm64
$ echo $CROSS_COMPILE
aarch64-ostl-linux-
$ echo $CC
aarch64-ostl-linux-gcc -mcpu=cortex-a35+crc -mbranch-protection=standard --sysroot=/opt/stm32mp2/5.0.15-snapshot/sysroots/cortexa35-ostl-linux
aarch64-ostl-linux-gcc -mcpu=cortex-a35+crc -mbranch-protection=standard --sysroot=/opt/stm32mp2/5.0.15-snapshot/sysroots/cortexa35-ostl-linux
$ echo $CXX
aarch64-ostl-linux-g++ -mcpu=cortex-a35+crc -mbranch-protection=standard --sysroot=/opt/stm32mp2/5.0.15-snapshot/sysroots/cortexa35-ostl-linux
aarch64-ostl-linux-g++ -mcpu=cortex-a35+crc -mbranch-protection=standard --sysroot=/opt/stm32mp2/5.0.15-snapshot/sysroots/cortexa35-ostl-linux
$ $CC --version
aarch64-ostl-linux-gcc (GCC) 13.4.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ echo $OECORE_SDK_VERSION
5.0.15-openstlinux-6.6-yocto-scarthgap-mpu-v26.02.18
-----------------------------------------------------------------------
$ git clone https://github.com/ChunghanYi/wireguard-auto
$ cd wireguard-auto
먼저 (Ubuntu Linux 상에서 server를 돌리기 위해) x86_64용 binary를 build해 보도록 하자.
$ $ ./build.sh clean
$ ./build.sh release
자, Auto connection server(wg_autod)가 준비되었으니, 이를 실행하도록 하자.
$ cd build
$ sudo ./wg_autod --help
$ sudo ./wg_autod --foreground --config ../config/server.conf
다음으로 (target board 상에서 client를 돌리기 위해) arm64용 binary를 만들어 보도록 하자.
$ ./build_arm64_yocto.sh clean
$ ./build_arm64_yocto.sh release
이번에는 Auto connection client wg_autoc 및 config file을 target board로 복사하도록 한다.
$ scp build/wg_autoc root@192.168.8.228:~/workspace
$ scp config/client.conf root@192.168.8.228:~/workspace
<Target board>
wg_autoc가 필요로 하는 디렉토리 및 파일을 생성한다(당분간은 수동 설정을 한다).
root@stm32mp2-e3-d2-e5:~/workspace# mkdir -p /qrwg/config
root@stm32mp2-e3-d2-e5:~/workspace# cp ./client.conf /qrwg/config
root@stm32mp2-e3-d2-e5:~/workspace# wg genkey | tee ./privatekey | wg pubkey > ./publickey
root@stm32mp2-e3-d2-e5:~/workspace# cp ./privatekey /qrwg/config
root@stm32mp2-e3-d2-e5:~/workspace# cp ./publickey /qrwg/config
root@stm32mp2-e3-d2-e5:~/workspace# vi /qrwg/config/client.conf
-> client.conf 파일 내용 중, this_public_key 값을 publickey file 내용으로 교체한다.
#
# wireguard autoconnect client configuration file
#
debug_mode = 1
server_port = 51822
#this part ----------------------------------------------------------
this_vpn_ip = 10.1.1.200
this_vpn_netmask = 255.255.255.0
this_public_key = "uG6i/g0v0KrKZX3nlfzmQwxk/ushtY8p/GXMO7GNGRg="
this_endpoint_ip = 192.168.8.228
this_endpoint_port = 51820
this_allowed_ips = "10.1.1.0/24,192.168.0.0/16"
# wireguard autoconnect client configuration file
#
debug_mode = 1
server_port = 51822
#this part ----------------------------------------------------------
this_vpn_ip = 10.1.1.200
this_vpn_netmask = 255.255.255.0
this_public_key = "uG6i/g0v0KrKZX3nlfzmQwxk/ushtY8p/GXMO7GNGRg="
this_endpoint_ip = 192.168.8.228
this_endpoint_port = 51820
this_allowed_ips = "10.1.1.0/24,192.168.0.0/16"
~
다음으로, wireguard interface wg0를 생성하고, 기본 설정을 한다(단, 이 부분은 wg_autoc에서도 처리해주긴 한다).
root@stm32mp2-e3-d2-e5:~/workspace# ip link add dev wg0 type wireguard
root@stm32mp2-e3-d2-e5:~/workspace# ip address add dev wg0 10.1.1.200/24
root@stm32mp2-e3-d2-e5:~/workspace# ip link set up dev wg0
root@stm32mp2-e3-d2-e5:~/workspace# wg set wg0 listen-port 51820 private-key /qrwg/config/privatekey
이제, wg_autoc를 본격적으로 실행할 차례이다.
root@stm32mp2-e3-d2-e5:~/workspace# ./wg_autoc --foreground --server 192.168.8.162 --config /qrwg/config/clien
t.conf[그림 11.3.3] Auto connection client wg_autoc 실행하기
📌 192.168.8.162는 Auto connection server가 실행되고 있는 Ubuntu PC의 ip이다.이 상태에서 wg show 명령을 확인해 보면, wireguard 설정이 제대로 먹힌(?) 것을 알 수 있다.
OK, 이 상태에서 상호간 ping을 시도해 보면 역시나 정상 동작한다. 😘
<Ubuntu 22.04 LTS>
$ ping 10.1.1.1
[그림 11.3.5] ping 10.1.1.1 from server to client
<STM32MP257F-DK board>
# ping 10.1.1.254
[그림 11.3.6] ping 10.1.1.254 from client to server
이상으로 STM32MP257F-DK board에 wireguard & wireguard-auto client를 올려 보는 과정을 가볍게 살펴 보았다.
4) WireGuard와 ROS 2의 만남
ROS 2는 상호간 통신 보안을 위해 DDS level에서의 security 기능(SROS 2: Secure ROS 2)을 지원한다. 따라서 이를 활용하면 node간 상호 인증은 물론이고, node간 통신 시 전달되는 data를 안전하게 보호할 수가 있다. 다시 말해 ROS 2 기반의 robot류를 운용하면서 발생하는 security issue를 대부분 cover할 수 있다는 얘기다. 하지만, 여기에 VPN 기술을 추가로 적용해 준다면, SROS 2를 통해서는 얻을 수 없는 많은 이점을 누릴 수가 있다. 💢
안전한 Robot 제어를 위해 VPN이 필요한 이유
- 원격 액세스 보안(인터넷/LTE): Robot이 로컬 영역 네트워크(LAN)에 연결되어 있지 않은 경우, 운영자와 robot이 서로를 "인식"할 수 있도록 VPN 또는 유사한 터널(예: DDS 라우터)을 사용해야 한다.
- 개방형 포트 숨기기: VPN이 없으면 포트 포워딩을 사용하여 로봇을 인터넷에 노출해야 할 수 있는데, 이는 보안에 매우 취약하다(뿐만아니라 Access Point의 포트 포워딩 설정을 일일히 해주어야 하므로 매우 불편하다). VPN은 모든 트래픽이 단일 보안 터널을 통해 통과하도록 하여 해커가 공격할 수 있는 개방형 포트를 없애준다.
- 신뢰할 수 없는 네트워크를 통한 암호화: DDS 보안에서 트래픽을 암호화할 수 있지만, VPN을 사용하면 DDS 보안 설정이 잘못되었더라도 모든 트래픽이 VPN 계층에서 암호화되어 제어 신호와 센서 데이터가 가로채기로부터 보호된다.
- NAT 및 방화벽 우회: 모바일 robot은 종종 LTE를 사용하는데, LTE는 직접적인 수신 트래픽을 제한한다(LTE 망과 인터넷 경계에 대용량 NAT가 있기 때문). VPN은 방화벽과 NAT를 통해 P2P 연결을 허용한다.
📌 eProsima사에서 만든 DDS Router를 이용하면 Robot node간의 safe 원격 통신이 가능하다고 한다.
참고로, ROS 2에 VPN 기술을 접목한 Husarnet이라는 P2P VPN 제품도 눈에 띈다.
필자는 ROS 2 보안을 강화하기 위한 VPN solution으로 (다른 무엇보다도) WireGuard가 적합하다고 믿는다. 😍
<ROS 2에 WireGuard VPN 적용 검토>
좀 더 구체적으로 들어가 보면, ROS 2의 node간 통신은 DDS(FastDDS or CycloneDDS 등)를 기반으로 하는데, 얘가 기본적으로 multicast 통신을 한다. 한편, WireGuard는 Layer 3 & unicast UDP를 기반으로 통신하는 구조이므로 ROS 2 over WireGuard 방식은 근본적으로 동작하지 않는다. 따라서 이를 해결하기 위해서는 ROS 2 node간 통신 시 unicast 방식을 사용하도록 조정(A)하거나, wireguard가 Layer 2 mode로 동작할 수 있는 구조로 변경(B)되어야 한다.
(A) ROS 2 node간 통신 시 unicast 방식을 사용하도록 조정
------------------------------------------------------------------------
아래와 같이 설정하면, node간의 unicast 통신이 가능하다.
<talker - STM32MP257F-DK>
=========================
root@stm32mp2-e3-d2-e5:~# export ROS_DOMAIN_ID=1
root@stm32mp2-e3-d2-e5:~# export ROS_DISCOVERY_SERVER="192.168.8.139:11888"
root@stm32mp2-e3-d2-e5:~# ros2 run demo_nodes_cpp talker
[INFO] [1775199322.576441590] [talker]: Publishing: 'Hello World: 1'
[INFO] [1775199323.576456273] [talker]: Publishing: 'Hello World: 2'
[INFO] [1775199324.575949436] [talker]: Publishing: 'Hello World: 3'
[INFO] [1775199325.575858594] [talker]: Publishing: 'Hello World: 4'
[INFO] [1775199326.575848053] [talker]: Publishing: 'Hello World: 5'
[INFO] [1775199327.575859861] [talker]: Publishing: 'Hello World: 6'
[INFO] [1775199328.575923719] [talker]: Publishing: 'Hello World: 7'
<listener - ubuntu 24.04LTS>
=========================
chyi@earth-new:~$ fastdds discovery -i 0 -l 192.168.8.139 -p 11888
### Server is running ###
Participant Type: SERVER
Security: NO
Server ID: 0
Server GUID prefix: 44.53.00.5f.45.50.52.4f.53.49.4d.41
Server Addresses: UDPv4:[192.168.8.139]:11888
chyi@earth-new:~$ export ROS_DISCOVERY_SERVER="192.168.8.139:11888"
chyi@earth-new:~$ ros2 daemon stop
The daemon is not running
chyi@earth-new:~$ ros2 run demo_nodes_cpp listener
[INFO] [1775199649.551148814] [listener]: I heard: [Hello World: 328]
[INFO] [1775199650.551274702] [listener]: I heard: [Hello World: 329]
[INFO] [1775199651.551213915] [listener]: I heard: [Hello World: 330]
[INFO] [1775199652.551093617] [listener]: I heard: [Hello World: 331]
[INFO] [1775199653.551098633] [listener]: I heard: [Hello World: 332]
[INFO] [1775199654.550953280] [listener]: I heard: [Hello World: 333]
[INFO] [1775199655.551005417] [listener]: I heard: [Hello World: 334]
------------------------------------------------------------------------
이 상태에서는 wireguard vpn을 적용하는 것이 충분히 가능하다고 말할 수 있다.
(B) wireguard가 Layer 2 mode로 동작할 수 있는 구조로 변경
Layer 2 wireguard와 관련해서는 이전 posting에서 자세히 다룬 바가 있다. 관심있는 분들은 아래 내용을 참조하기 바란다. 😋
[그림 11.4.4] L2 wireguard를 활용하여 안전하게 ROS 2 robot control 하기
---------------------------------------------------------------------------------------/ 💢
지금까지 7차례에 걸쳐서 STM32MP257F-DK board를 활용한 embedded linux programming에 관하여 살펴 보았다. 부족한 내용이지만, 끝까지 읽어주신 독자 여러분에게 감사의 말씀을 전한다. 😊
May the source be with you~
References
[1] https://www.st.com/en/evaluation-tools/stm32mp257f-dk.html
[2] UM3385 - Discovery kit with STM32MP257F MPU - User manual, STMicroelectronics.
[3] Data brief - STM32MP257F-DK, STMicroelectronics.
[4] STM32MP251C/F STM32MP253C/F, STM32MP255C/F STM32MP257C/F Datasheet, STMicroelectronics.
[5] STM32MP257-DK schematic, STMicroelectronics.
[6] RM0457 Reference manual, STM32MP23/25xx advanced Arm®-based 32/64-bit MPUs
[7] https://wiki.st.com/stm32mpu/wiki/Getting_started/STM32MP2_boards/STM32MP257x-DK
[8] https://wiki.st.com/stm32mpu/wiki/STM32MP2_boot_chain_overview
[9] https://wiki.st.com/stm32mpu/wiki/STM32MPU_Distribution_Package
[10] https://www.st.com/en/microcontrollers-microprocessors/stm32mp257f.html
[11] https://wiki.st.com/stm32mpu/wiki/Linux_remoteproc_framework_overview#Remote_processor_boot_through_sysfs
[12] https://wiki.st.com/stm32mpu/wiki/Category:Buildroot-based_Linux_embedded_software
-> STM32MP documents
[13] https://www.barkhauseninstitut.org/research/lab-1/our-blog/posts/ros2-wireguard-lte
[14] https://husarnet.com/robotics
[15] https://husarnet.com/blog/ros2-dds-router
[16] https://github.com/tuw-robotics/ros2_cyclonedds_wireguard
[17] https://dev.to/sebos/securing-ros2-nodes-with-sros2-encryption-and-permissions-for-robot-communications-m55
[18] https://eprosima-dds-router.readthedocs.io/en/latest/index.html
-> ROS 2 + VPN
[19] And Google and Gemini~
Slowboot

























