1편에서 AP와 Pi-hole까지 세웠다. 빨라진 건 알겠는데 얼마나 빨라졌는지는 몰랐다. "체감상 빠르다"에서 멈춰 있었던 셈이다. 이번엔 제대로 재봤고, 재는 김에 모니터링도 붙였다.
그전까지는 2.4GHz 채널 6이었다. 파이가 노트북 바로 옆에 있으니 5GHz의 약점인 벽 통과 감쇠는 신경 쓸 이유가 없었다.
band만 바꾸려니 거부당했다.
Error: 802-11-wireless.channel: '6' is not a valid channel
채널 6은 2.4GHz 전용이다. 5GHz band와 같이 설정될 수가 없다. 채널을 먼저 비우고, band를 바꾸고, 새 채널을 넣는 순서로 가야 한다.
nmcli connection modify pi-ap 802-11-wireless.channel ""
nmcli connection modify pi-ap 802-11-wireless.band a
nmcli connection modify pi-ap 802-11-wireless.channel 36
nmcli connection down pi-ap && nmcli connection up pi-ap
마지막 down/up을 빼먹으면 설정만 바뀌고 실제 AP는 예전 채널 그대로다. 나는 이걸 안 한 채로 iw dev wlan0 info를 봤다가 채널이 안 바뀐 줄 알고 한참 헤맸다.
미국 5GHz는 대역마다 규제가 다르다.
iw reg get으로 확인된다. band만 지정하고 채널을 비워두면 파이가 알아서 DFS 채널을 골라버려서 AP가 아예 안 뜨기도 한다.
| 구성 | 속도 |
|---|---|
| 학교 와이파이 | 17 Mbps |
| PiLab 2.4GHz / 20MHz | 55 Mbps |
| PiLab 5GHz / 20MHz | 62 Mbps |
| PiLab 5GHz / 80MHz | 97 Mbps |
5GHz로 옮긴 건 13% 개선에 그쳤다. 채널 폭을 80MHz로 넓히자 56%가 뛰었다.
nmcli connection modify pi-ap 802-11-wireless.channel-width 80mhz
5GHz의 진짜 장점은 주파수가 높은 게 아니라 채널을 넓게 쓸 수 있다는 데 있었다. 20MHz로 쓰면 2.4GHz와 별 차이가 없다.
여기서 끝낼 수도 있었다. 속도 5.9배면 성과로는 충분하니까. 그래도 지연과 손실을 재봤다.
| 지표 | 학교 와이파이 | PiLab |
|---|---|---|
| 다운로드 | 17 Mbps | 97 Mbps |
| 평균 RTT | 14 ms | 12 ms |
| 최대 RTT | 22 ms | 17 ms |
| 패킷 손실 | 0% | 0% |
| DNS 첫 조회 | 35 ms | 3 ms |
| DNS 캐시 히트 | 없음 | 0 ms |
속도만 5.9배 차이가 났다. 지연은 2ms 줄었고 손실은 양쪽 다 0%였다.
신호가 약하면 낮은 변조 방식으로 떨어지고 재전송이 늘어난다. 그런데 ping은 32바이트짜리라 그 조건에서도 무리 없이 통과한다. 큰 파일은 다르다. 낮은 전송률이 그대로 누적되니까. 작은 패킷은 멀쩡한데 큰 파일만 느린 상태였다.
방에서 느꼈던 "느리다"는 대역폭 이야기였다. 응답이 굼뜬 게 아니라 많이 받을 때만 느렸다. 재보기 전까지는 둘을 구분하지 못했다.
참고로 파이 유선은 평균 9.33ms에 편차 0.046ms가 나왔다. 무선 구간이 얹는 비용이 3ms 정도인 셈이다.
node_exporter, Prometheus, Grafana를 올렸다. 2GB 램에 무리일까 싶었는데 셋을 합쳐 400MB 남짓이었다.
기존 exporter를 쓰려다 포기했다. arm64 바이너리가 없다. 마지막 릴리스도 Pi-hole v5 API 기준이라 v6에서는 인증부터 막힌다.
그래서 SQLite를 직접 읽기로 했다. Prometheus 텍스트 형식으로 파일에 쓰고 node_exporter의 textfile 컬렉터로 노출하는 방식이다.
파이썬 스크립트 (cron 1분) → .prom 파일 → node_exporter → Prometheus → Grafana
프로세스를 하나 더 띄우지 않아도 되고, 넣고 싶은 지표를 마음대로 넣는다.
웹 UI는 25.8%인데 내가 만든 지표는 62.56%였다.
Pi-hole은 질의마다 status 코드를 남긴다. 차단으로 볼 코드를 추측해서 넣었는데 그중 17번이 범인이었다. 분포를 보니 하루 11,007건, 전체 2위였다.
SELECT status, COUNT(*) FROM queries
WHERE timestamp > strftime('%s','now') - 86400
GROUP BY status ORDER BY COUNT(*) DESC;
17을 빼니 36.4%. 같은 시각 웹 UI도 36.4%였다.
이미 아는 값과 대조하지 않았으면 틀린 숫자로 대시보드를 만들었다. 62%가 눈에 띄게 이상해서 걸렸지, 30%쯤으로 나왔으면 그냥 넘어갔다.
클라이언트 IP 대신 기기 이름을 쓰려고 Tailscale에서 이름을 끌어왔다. 결과가 이랬다.
pihole_client_queries_24h{client="localhost"} 32835
iOS 기기의 HostName이 전부 localhost였다. 기기가 스스로 보고하는 값을 iOS가 그렇게 내놓는다. 아이폰과 아이패드가 한 줄로 합쳐진 이유다.
관리 콘솔에 보이는 이름은 DNSName 필드에 따로 있었다. 첫 마디만 떼서 쓰니 풀렸다.
덧붙이면 같은 기기가 Tailscale 주소와 AP 주소 두 개로 잡힌다. CurAddr 필드에 현재 직접 연결 주소가 들어 있어서 그걸로 묶었다. 다만 릴레이를 타거나 기기가 꺼져 있으면 이 값이 비어서 잠깐 두 줄로 갈라진다.
이번 편에서 배운 것.
다음 편은 방화벽 재설계와 클라이언트 격리, 그리고 DNS 로그에서 이상 패턴을 찾아내는 파이프라인이다.