You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

6.4 KiB

Wi-Fi AP 서브시스템 가이드

살아있는 문서(living guide) — 앱 v1.11.10 기준. 코드: src/network/ap_*.py, deploy/dpworld-ap-apply.sh. 아키텍처 전체는 architecture.md §3.1.1.

장비를 소프트 AP(ap0)로 띄워 운영자가 무선으로 Web Configurator(:9090)에 접속하게 한다. STA(wlan0, 업스트림 Wi-Fi)는 무접촉으로 유지한다.


1. ap0 가상 인터페이스 (vif)

  • wlan0 위에 iw dev wlan0 interface add ap0 type __ap별도 vif 생성.
  • MAC: wlan0 MAC 첫 옥텟에 local-admin bit(0x02)를 OR 해서 별도 MAC 부여 (ap_mac() in dpworld-ap-apply.sh) — STA 와 충돌하지 않는 LA-bit 주소.
  • 채널 = SCC(Single-Channel Concurrency): 기본(ap_band=auto)은 STA 가 붙어 있는 채널을 추종한다(ap_engine.resolve_channel). 단일 라디오는 동시에 한 채널만 쓸 수 있어, STA 와 AP 가 같은 채널이어야 둘 다 동작한다. STA 미연결 시 2.4GHz 채널 6 으로 폴백. 2g/5g 명시(MCC)는 옵트인이며 STA 와 채널이 갈리면 한쪽이 끊길 수 있다.

2. ap_engine 라이프사이클

ApEngine(src/network/ap_engine.py)이 적용을 오케스트레이션한다. 직렬화 lock 으로 동시 apply 의 tmp 파일 경합·서비스 중복 start 를 막는다.

  1. ap_config → intent 정규화(ap_model.ap_intent_from_db).
  2. validate_ap() hard-rule 검증 → 실패 시 상태 REJECTED(파일 미작성).
  3. 활성화면: 채널 산정 → hostapd-ap0.conf / udhcpd-ap0.conf 렌더(0600, 디렉터리 0700) → marker ap-enabled 작성. 비활성화면 marker 제거.
  4. systemctl start dpworld-ap-apply.service 트리거(oneshot, dpworld-ap-apply.sh 실행).
  5. 결과 상태 persist: APPLYINGCOMMITTED / FAILED.

상태값: REJECTED, APPLYING, COMMITTED, FAILED.

marker = kill-switch

/home/root/network/ap/ap-enabled 파일의 존재 여부가 enable/disable 판정 기준이다. dpworld-ap-apply.sh 는 marker 가 있으면 ap_up, 없으면 ap_down(멱등 정리)을 한다.


3. ap_config DB 키 + 필드

별도 board_config 키 — Python 전용(device_config 무관, Java/dpworldapp 미사용). db_manager.ALLOWED_KEYS 에 등록됨. 기본값(ap_model.DEFAULT_AP_CONFIG):

필드 기본값 설명
ap_enabled false AP on/off
ap_ssid "" SSID (최대 32 byte, "·\·#·제어문자 금지)
ap_passphrase "" WPA2-PSK passphrase (8–63 byte, 동일 금지문자)
ap_band "auto" auto(SCC) / 2g / 5g
ap_channel 0 0 = auto. band 별 유효 채널만 허용
ap_hidden false SSID 브로드캐스트 숨김
ap_ip 192.168.50.1 AP 게이트웨이 IP (/24)
dhcp_start 192.168.50.50 DHCP 풀 시작 (AP 서브넷 내)
dhcp_end 192.168.50.150 DHCP 풀 끝
dhcp_lease 43200 리스 시간(초)

검증은 ap_validator.validate_ap — SSID/PSK 바이트 길이, hostapd-conf 인젝션 차단 (#·따옴표·역슬래시·개행), 채널-밴드 정합, DHCP 범위가 AP /24 서브넷 안인지·AP IP 와 겹치지 않는지, 그리고 유효한 country regdomain 이 있어야 활성화 가능 (country_pending이면 "reboot required").


4. systemd 유닛 (deploy/)

유닛 역할
dpworld-ap-apply.service oneshot — dpworld-ap-apply.sh 실행(엔진이 on-demand start, [Install] 없음). --boot(seed)/무인자(on-demand)
dpworld-ap-seed.service 부팅 시 marker 기준 AP 재구성(seed)
dpworld-hostapd-ap0.service hostapd /home/root/network/ap/hostapd-ap0.conf
dpworld-udhcpd-ap0.service udhcpd (ap0 DHCP 서버)

dpworld-ap-apply.sh 가 vif 생성 → MAC 설정 → IP 부여 → 방화벽 → hostapd/udhcpd restart 순으로 멱등 reconcile 한다(ap_up). 어느 단계든 실패하면 ap_down 으로 fail-closed.


5. 방화벽 (v1.11.7)

ap0 전용 iptables chain(DPWORLD_AP_IN / DPWORLD_AP_FWD)을 쓴다 — STA/eth 무영향.

  • INPUT(장치 자체): 전면 개방(SSH 22 포함). 즉 WPA2 PSK 가 유일한 접근 게이트. (이전 default-deny[9090/DHCP/ICMP 만 허용]에서 v1.11.7 에 전환 — 현장 관리 접근성 우선, 비밀번호 강화 전제.)
  • FORWARD(경유): blanket DROP. ip_forward=1 이어도 AP 클라이언트가 PLC(eth1)·업링크로 라우팅하는 것을 전면 차단 = provisioning 격리(PLC/내부망 보호). 이 격리는 유지된다.

★ 요약: AP 클라이언트는 장치 자체엔 접근 가능하나(PSK 통과 시), 내부망/PLC 로는 경유 불가.


6. API

Method Path 비고
GET /api/network/ap/status 라이브 상태 — 응답에서 ap_passphrase 제거(미인증 API)
POST /api/network/ap/config ap_config 저장(필드 화이트리스트 merge, 알 수 없는 키 400)
POST /api/network/ap/apply bring-up/down 적용. {"dry_run": true} 면 적용 없이 config 회신(PSK 제거)

status 응답: ap_enabled·ap0_up·hostapd_running·clients·country_pending + 마스킹된 config. 서브시스템 import 실패(예: Windows dev box) 시 503 fail-soft.

API 인증 없음: :9090 은 현재 미인증(문서화된 threat boundary). AP 가 열리면 PSK 만이 게이트이므로 강한 AP PSK 가 사실상의 1차 방어선이다. 운영자 로그인은 설계 백로그 (architecture.md §10).


7. kill-switch (수동 비활성화)

엔진/웹이 응답하지 않을 때 root 셸에서 즉시 AP 를 내릴 수 있다:

rm /home/root/network/ap/ap-enabled && /usr/bin/dpworld-ap-apply.sh

marker 가 사라지면 스크립트가 ap_down(데몬 stop + 방화벽 flush + ap0 삭제)을 수행한다.


8. ⚠ flash 생존 caveat

/home/root/network/ap/*(config·marker)와 /opt 상태는 펌웨어 flash 후에도 생존한다. 그러나 deploy/ 의 systemd 유닛·dpworld-ap-apply.sh 는 rootfs(/lib, /usr/bin)에 설치되며 flash 마다 wipe 된다. 따라서 flash 후에는 AP 유닛/스크립트를 재설치해야 AP 가 다시 뜬다. 근본 해결(BSP 이미지 베이킹)은 백로그 — firmware-ota-guide.md §6 및 메모리 web-survives-flash 참조.