2026년 4월 12일 일요일

Embedded Linux Programming with STM32MP257F-DK board(Episode VII)

거의 6년만에 STM32MP 보드를 다시 하나 입수했다(이번에는 STM32MP257F-DK 보드다). 이번 시간 부터는 앞으로 몇차례에 걸쳐서, STM32MP257F-DK 보드 기반 embedded linux와 관련한 다양한 주제를 다뤄 보고자 한다. 이번이 그 일곱번째 시간(마지막)이다. 😎

 
The last episode

목차
References

KeywordsSTM32MP257F-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라는 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를 해 보도록 한다.

devtool build linux-stm32mp
  -> 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 주소를 설정한 후,

[그림 11.1.5] Target board - ifconfig -a 명령 실행 모습

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

[그림 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 \

"
...

$ bitbake st-image-weston
 -> OK, wireguard.ko & wg tool 등이 image에 제대로 통합되었다(build 시간도 오래 걸리지 않는다).

정상 build가 진행되었으니, 1 장에서 소개한 대로, STM32CubeProgrammer를 사용하여 SDcard Image를 다시 설치하도록 한다.

[그림 11.2.3] STM32CubeProgrammer로 새 image 설치하기

부팅 후, target board에 wireguard가 정상적으로 설치되어 있는지 확인해 본다.

$ sudo minicom -D /dev/ttyACM0

root@stm32mp2-e3-d2-e5:~# modprobe wireguard
[  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.

 
[그림 11.2.4] modprobe wireguard and wg tool

이후, wireguard 관련 기본 설정을 진행하도록 하자.

[그림 11.2.5] wireguard 기본 설정하기

3) wireguard-auto project build 하기
이번 절에서는 필자가 개발하고 있는 wireguard-auto project를 stm32mp257f-dk board 상에서 돌려 보는 내용을 소개해 보고자 한다.

[그림 11.3.1] WireGuard AutoConnect Protocol(a.k.a WG PING-PONG protocol)

먼저, 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

$ echo $CXX
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

[그림 11.3.2] Auto connection server - wg_autod 실행하기 (On Ubuntu 22.04 LTS)

다음으로 (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 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 설정이 제대로 먹힌(?) 것을 알 수 있다.

[그림 11.3.4] wg show 명령 실행 모습

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 framework와 WireGuard를 엮는(?) 내용 - WireGuard를 활용하여 ROS 2 robot을 원격으로 안전하게 제어하는 solution 개발 - 에 대해 잠시 소개해 볼까 한다. 

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 원격 통신이 가능하다고 한다.
[그림 11.4.1] eProsima DDS Router 개요 [출처 - 참고문헌 18]

참고로, ROS 2에 VPN 기술을 접목한 Husarnet이라는 P2P VPN 제품도 눈에 띈다.

[그림 11.4.2] DDS Router와 Husarnet P2P VPN 적용 예 [출처 - 참고문헌 18]

필자는 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을 적용하는 것이 충분히 가능하다고 말할 수 있다.

[그림 11.4.3] wireguard를 활용하여 안전하게 ROS 2 robot control 하기

(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