3줄 요약
- esp32-remote-wol은 개발자 kreaxv가 2026년 2월에 깃허브에 공개한 ESP32용 Wake-on-LAN 펌웨어다. 집 네트워크가 CGNAT 환경이거나 공인 IP가 없으면 포트포워딩을 쓸 수 없는데, 이런 집에서도 외부에서 PC를 켤 수 있게 하는 것이 이 펌웨어의 목적이다. MIT 라이선스이고, 10월 6일 기준으로 스타 128개와 포크 14개를 받았다.
- 집에 둔 ESP32는 MQTT 브로커에 먼저 접속해 연결을 유지하다가, 기기 전용 토픽으로 PC의 MAC 주소를 받으면 로컬 네트워크에 매직 패킷을 브로드캐스트한다. 개발자가 운영하는 웹 페이지를 열면 펌웨어 설치와 Wi-Fi 설정, 원격 깨우기를 모두 브라우저에서 할 수 있다.
- 펌웨어는 기본값으로 소스 코드에 적힌 공용 계정을 써서 개발자의 HiveMQ Cloud 브로커에 접속하고, 기기마다 다른 토픽은 ESP32 MAC 주소의 SHA-256 해시로 만든다. 3월에 펌웨어를 다시 쓰는 과정에서 명령 형식 검사 코드가 삭제됐고, 그 때문에 README의 일부 설명이 현재 코드와 맞지 않는다.
Wake-on-LAN과 CGNAT
Wake-on-LAN은 꺼진 PC의 네트워크 카드가 정해진 형식의 패킷을 받으면 전원을 켜는 기능이다. 이 패킷을 매직 패킷이라고 부르며 보통 UDP 브로드캐스트로 보낸다. 브로드캐스트 패킷은 같은 로컬 네트워크의 기기에만 전달된다. 인터넷에서 들어온 패킷을 공유기가 로컬 네트워크 전체에 브로드캐스트하는 일은 없다. 외부에서 집 PC를 켜려면 공유기에 포트포워딩을 설정해 두거나, 집에 늘 켜 둔 다른 기기가 대신 패킷을 보내도록 해야 한다.
CGNAT(Carrier-Grade NAT)는 통신사가 여러 가입자에게 공인 IP 하나를 함께 쓰게 하는 방식이다. 이 환경에서는 집 공유기가 공인 IP를 따로 받지 못하므로 포트포워딩을 쓸 수 없고, 외부에서 집 공유기로 먼저 접속할 방법도 없다. esp32-remote-wol은 집에 있는 ESP32가 외부 브로커에 먼저 접속하게 해서 이 문제를 해결한다. README는 동작 과정을 네 단계로 설명한다.
- ESP32가 Wi-Fi에 연결한다.
- ESP32가 MQTT 브로커와 아웃바운드 연결을 유지한다.
- ESP32가 자신에게 배정된 토픽을 구독한다.
- 올바른 메시지가 오면 로컬 네트워크에 Wake-on-LAN 패킷을 보낸다.
README는 Wake-on-LAN이 로컬 네트워크에서 이미 동작하고 있어야 한다는 조건을 따로 적어 두었다. 공식 설정 안내 페이지는 BIOS 또는 UEFI 설정과 운영체제 설정에서 모두 이 기능을 켜야 한다고 설명하고, 유선 이더넷 연결이 가장 안정적이라고 덧붙인다.
공식 웹 인터페이스로 설정하기
README는 개발자가 운영하는 웹 인터페이스(ewol.top)를 기본이자 권장 방식으로 소개한다. 설정은 다음 순서로 진행한다.
- 설정 페이지의 Install Firmware 버튼으로 ESP32에 펌웨어를 설치한다. 설치 페이지는 ESP Web Tools를 쓰므로 웹 시리얼(Web Serial)을 지원하는 데스크톱 크롬이나 엣지가 필요하다.
- 설치가 끝나면 같은 페이지에서 Wi-Fi 이름과 비밀번호를 입력한다. 펌웨어에 포함된 Improv Wi-Fi 라이브러리가 USB 시리얼로 이 정보를 받는다.
- Wi-Fi에 연결된 ESP32는 포트 80에서 작은 웹 페이지를 제공하며, 이 페이지에 자신의 MAC 주소를 표시한다. 이 값을 복사해 둔다.
- ESP32를 재시작한다.
- 홈 화면에 ESP32의 MAC 주소와 깨울 PC의 MAC 주소를 입력하고 Wake 버튼을 누른다.
개발자의 설정 안내 영상 「ESP32 WoL」(Krea XV 유튜브)의 한 장면. 펌웨어 설치 직후 브라우저에 Wi-Fi 설정 창이 뜬다. 영상을 촬영할 때는 웹 인터페이스가 옛 도메인을 쓰고 있었다.
ewol.top 홈 화면(2026년 10월 6일 캡처). 홈 화면에서는 두 MAC 주소만 입력하면 깨우기 요청을 보낼 수 있다.
홈 화면의 스크립트는 입력값을 서버의 /wake 경로에 POST로 보낸다. 요청 본문은 두 값으로 이루어진다. 하나는 콜론을 지우고 소문자로 바꾼 ESP32의 MAC 주소이고, 다른 하나는 콜론으로 구분한 대문자 형식의 PC MAC 주소다. 로그인이나 계정 절차는 없고, 마지막으로 성공한 값은 브라우저의 로컬 스토리지에 저장해 둔다. 이 요청을 받아 브로커에 메시지를 발행하는 서버 코드는 깃허브 저장소에 공개되어 있지 않다.
웹 인터페이스 주소는 원래 wol.kreaxv.top이었다. 지금 홈 화면은 새 도메인 ewol.top을 북마크하라고 안내하면서 옛 도메인이 2026년 10월 7일에 만료된다고 알린다. README의 주소도 10월 3일 커밋에서 새 도메인으로 바뀌었다.1
펌웨어 코드
펌웨어 코드는 src/main.cpp 파일 하나에 모두 들어 있고, 156줄 분량이다. 구성 요소를 정리하면 다음과 같다.
| 구성 | 구현 |
|---|---|
| Wi-Fi 설정 | Improv Wi-Fi 라이브러리(USB 시리얼). 부팅하면 WiFi.begin()으로 저장된 정보를 써서 재접속 |
| 브로커 연결 | PubSubClient 라이브러리, TLS 포트 8883. 서버 인증서는 검증하지 않음(setInsecure()) |
| 기기 식별 | Wi-Fi MAC 주소를 소문자 16진수 12자리로 바꾼 뒤 SHA-256 해시를 계산해 토픽 wol/<해시>로 사용 |
| 깨우기 | UDP 포트 9로 브로드캐스트하는 102바이트 매직 패킷(0xFF 6바이트 뒤에 PC의 MAC 주소 6바이트를 16번 이어 붙인 형태) |
| 기기 웹 페이지 | 포트 80. ESP32의 MAC 주소 표시 |
빌드 설정 파일 platformio.ini는 ESP32, ESP32-S2, ESP32-S3, ESP32-C2, ESP32-C3, ESP32-C5, ESP32-C6, ESP32-C61까지 여덟 가지 칩의 빌드 환경을 정의한다.2 README는 칩만 맞으면 보드 제조사는 상관없다고 설명한다. 이 파일에는 첫 줄부터 경고도 적혀 있다. 부팅을 계속 되풀이하거나 Wi-Fi 설정 창이 나타나지 않으면 보드 종류를 잘못 고른 것이니, 맞는 프로필로 다시 설치하라는 내용이다.3
기본 브로커와 공용 계정
펌웨어 소스에는 HiveMQ Cloud의 브로커 주소와 사용자 이름 client, 비밀번호가 그대로 적혀 있다. 2월 커밋에서 추가됐던 주석은 이 브로커를 “Default demo MQTT broker"라고 설명했다. 기본 설정 펌웨어를 설치한 사람들이 모두 계정 하나를 함께 쓰는 셈이고, 브로커가 각 기기를 구분할 수 있는 근거는 토픽 이름 하나뿐이다. 브로커가 계정별로 구독할 수 있는 토픽을 제한하는지는 깃허브 저장소만으로는 알 수 없다.
USE_HASHED_ID는 토픽 이름을 해시로 만들지 정하는 설정이고, 기본값은 1이다. 토픽에 MAC 주소가 그대로 드러나지 않게 하려는 장치이며, README 보안 항목의 “Optional hashed identifiers"에 해당한다.
직접 운영하는 브로커를 쓰는 경우
기본 HiveMQ 브로커 대신 직접 운영하는 브로커를 쓰려면 USE_HASHED_ID를 0으로 바꾸고 브로커 주소, 포트, 계정을 고친 뒤 직접 빌드한다. README의 안내대로라면 토픽 wol/<ESP32_MAC>에 PC의 MAC 주소를 페이로드에 담아 발행하면 된다.
Topic: wol/1A:2B:3C:4C:5D:6F
Payload: 3C:52:82:11:9A:EF
그런데 해시를 쓰지 않을 때 현재 코드가 만드는 토픽은 이 예시와 형식이 다르다. 코드는 콜론 없는 소문자 16진수 12자리를 쓰므로, 이 예시의 기기가 실제로 구독하는 토픽은 wol/1a2b3c4c5d6f다. 또한 코드는 항상 TLS 클라이언트(WiFiClientSecure)로 브로커에 연결하므로, 직접 운영하는 브로커도 TLS 접속을 지원해야 한다.
README의 보안 항목과 현재 코드
README는 보안 항목에서 네 가지를 강조한다. 열린 포트도 들어오는 연결도 없고, 기기는 자신의 토픽만 구독하며, 식별자를 해시로 바꾸는 기능은 선택해서 쓸 수 있다고 한다. 인터넷에서 기기로 접속하는 경로가 없다는 설명은 코드와 일치한다. 포트 80의 기기 웹 페이지는 로컬 네트워크에서만 접근할 수 있고 MAC 주소만 표시한다. TLS 연결은 암호화되지만 setInsecure() 때문에 서버 인증서를 검증하지 않는다. 2월 버전에는 엄격한 TLS가 필요하면 이 설정 대신 CA 인증서를 쓰라는 주석이 달려 있었다.
README에는 “Invalid topic or payload is ignored"라고 적혀 있지만, 현재 코드는 이 설명대로 동작하지 않는다. 2월 버전 펌웨어는 메시지를 받으면 먼저 그 메시지의 토픽이 기기 자신의 토픽과 같은지 비교했다. 이어서 sscanf로 페이로드가 16진수 두 자리를 콜론으로 이은 XX:XX:XX:XX:XX:XX 형식인지 확인했고, 두 검사를 통과해야만 패킷을 보냈다. 3월 8일 커밋은 Wi-Fi 설정 방식을 WiFiManager 캡티브 포털에서 Improv로 바꾸면서 main.cpp를 다시 작성했다. 이 커밋에서 75줄이 추가되고 117줄이 삭제됐는데, 두 검사도 이때 함께 없어졌다. 현재 코드는 페이로드의 앞 17자를 정해진 위치대로 읽어 16진수로 변환하고, 16진수가 아닌 문자는 0으로 처리한다. 따라서 지금 펌웨어는 형식이 틀린 페이로드를 받아도 무시하지 않고, 엉뚱한 MAC 주소를 깨우는 매직 패킷을 보낸다.4
가장 흥미로운 지점
코드를 다 읽고 나서 나는 누가 이 PC를 깨울 수 있는지 따져 보았다. 공식 웹 인터페이스에는 로그인 절차가 없으므로, ESP32와 PC의 MAC 주소 두 개를 아는 사람이면 누구나 깨우기 요청을 보낼 수 있다. ESP32가 보내는 무선 프레임의 헤더에는 Wi-Fi MAC 주소가 암호화되지 않은 채 들어 있다. 신호를 수신할 수 있는 거리에 있는 사람이라면 이 값을 관찰할 수 있다.
토픽 해시가 MAC 주소를 감추는 효과도 약하다. 해시의 입력값은 MAC 주소 12자리이고, 그중 앞 6자리는 Espressif에 할당된 제조사 코드(OUI)다. 따라서 제조사 코드가 정해지면 나머지 6자리로 만들 수 있는 MAC 주소는 2의 24제곱, 약 1,677만 개다. 이 정도는 일반 PC로 금방 전부 계산할 수 있다. 해시가 효과를 내는 경우는 브로커의 토픽 목록을 본 사람이 MAC 주소를 그대로 읽으려 할 때뿐이다.
그런데 이 약점으로 입는 피해는 크지 않다. Wake-on-LAN 패킷으로 할 수 있는 일은 PC 전원을 켜는 것뿐이고, 켜진 PC에 접속하려면 별도의 인증이 필요하다. 아무리 나빠도 누군가 내 PC를 원하지 않는 시각에 켜는 일이 전부다. 개발자는 설정 없이 바로 쓰는 경험을 택했다. 그 대신 감수한 위험이 이 정도라면 납득할 만한 선택이라고 나는 생각한다.
3월에 펌웨어를 다시 쓰면서 설치 과정은 브라우저 버튼 하나로 단순해졌다. 하지만 입력 검사도 같은 커밋에서 지워졌고, README에는 그 검사가 지금도 적혀 있다. 나는 이 점이 아쉽다.
출처
kreaxv, esp32-remote-wol (GitHub, MIT License). 2026년 2월 2일 공개, 마지막 커밋 2026년 10월 3일.
원문: https://github.com/kreaxv/esp32-remote-wol
공식 웹 인터페이스: https://ewol.top/ (설정 안내 https://ewol.top/setup/)
설정 안내 영상: Krea XV, 「ESP32 WoL」 https://www.youtube.com/watch?v=V69Tiw9ggR8
커버의 구성도는 ewol.top 설정 페이지에 실린 그림이다. 웹 화면 캡처, 스타 수, 포크 수는 모두 2026년 10월 6일 기준이다.
펌웨어가 제공하는 기기 웹 페이지(
main.cpp의handleRoot)는 아직 옛 주소인 wol.kreaxv.top을 가리키는 링크를 쓴다. ↩︎웹 설치 페이지의 매니페스트(
manifest.json)는 ESP32-C61을 제외한 일곱 가지 칩용 바이너리만 제공한다. ESP32-C61 보드는 PlatformIO로 직접 빌드해야 한다. 또한 ESP32-C5에서는 웹 페이지로 Improv Wi-Fi 설정을 할 수 없다는 이슈 2번이 3월 19일에 등록됐고, 아직 해결되지 않았다. ↩︎모든 빌드 환경에는 CPU 80MHz, 플래시 DIO 모드와 40MHz, 플래시 용량 4MB 설정이 공통으로 들어가며, 파일 주석은 이 조합을 “safer universal settings"라고 부른다. ↩︎
공식 웹 인터페이스는 브라우저에서 MAC 주소 형식을 먼저 검사하므로, 이 차이는 직접 운영하는 브로커에 메시지를 발행할 때 주로 드러난다. 같은 재작성에서 Wi-Fi 연결 감시 코드와 브로커 재접속 간격 제한도 함께 삭제됐다. 감시 코드는 연결이 끊기면 20초마다 재접속을 시도하고, 180초가 지나면 기기를 재부팅했다. 재접속 간격 제한은 브로커 접속을 최소 3초 간격으로만 다시 시도하게 하는 코드였다. ↩︎
