Tailscale이 iptables를 찾지 못할 때 firewall mode를 확인하는 순서

firewall 구현과 netfilter 관리 수준은 다른 설정이다

Tailscale Linux 설정에는 혼동하기 쉬운 두 축이 있습니다. firewall mode는 tailscaled가 규칙을 조작할 때 iptables binary를 사용할지 nftables Netlink API를 사용할지 정합니다. netfilter mode의 on, nodivert, off는 Tailscale이 규칙을 만들고 연결할 범위를 정합니다. iptables 실행 파일이 없다는 오류를 보고 곧바로 netfilter mode를 off로 바꾸면 두 축을 섞게 됩니다.

공식 문서에 따르면 iptables firewall mode는 호환되는 iptables binary가 PATH에 있어야 합니다. nftables mode는 nft CLI가 아니라 Netlink API를 사용합니다. 따라서 nft 명령이 없다는 사실만으로 nftables mode가 불가능하다고 결론 내릴 수 없습니다.

단일 오류 줄이 아니라 선택 과정 전체를 남긴다

로그 또는 상태의미다음 확인
using iptablesiptables 구현이 선택됨binary와 호환 backend를 확인합니다.
iptables not found선택된 구현의 binary 실행 실패PATH와 package 상태를 확인합니다.
falling back to nftables오류 뒤 다른 구현으로 전환 시도바로 뒤의 최종 mode를 확인합니다.
using nftablesNetlink 기반 구현이 활성실제 Tailscale rule과 연결을 검증합니다.
procd crash loopdaemon 초기화가 반복 실패첫 실패 시점의 전체 log를 보존합니다.

먼저 읽기 전용 자료만 수집합니다. 전체 journal·status·UCI 설정에는 인증키와 장치 식별자가 있을 수 있으므로 아래처럼 private 임시 디렉터리에 저장합니다. 수집 명령이 실패하면 그 파일을 성공한 기록으로 취급하지 않습니다. 비밀값을 지운 오류 종류와 선택된 구현만 공유하고, 원본은 조사 뒤 자신의 보관 정책에 따라 정리합니다.

umask 077
DIAG_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tailscale-diag.XXXXXXXX") || exit 1
tailscale version
command -v iptables
iptables --version
sudo journalctl -u tailscaled -b --no-pager >"$DIAG_DIR/tailscaled.log" 2>&1
tailscale status --json >"$DIAG_DIR/status.json" 2>&1

OpenWrt에서는 systemd journal 대신 init과 logread를 사용합니다. 같은 재시작 구간을 묶어 봐야 fallback 뒤에 성공했는지 실제 crash loop로 끝났는지 알 수 있습니다.

umask 077
DIAG_DIR=$(mktemp -d /tmp/tailscale-diag.XXXXXX) || exit 1
/etc/init.d/tailscale status
logread -e tailscale >"$DIAG_DIR/tailscaled.log" 2>&1
uci export tailscale >"$DIAG_DIR/tailscale.uci" 2>&1

오류 뒤 최종 상태를 기준으로 분기한다

  • iptables 오류 뒤 using nftables가 나오고 node가 online: 한 줄의 경고만 보고 장애로 판단하지 않습니다. Tailscale IP 연결과 route 기능을 실제로 검증합니다.
  • iptables 오류 뒤 daemon이 종료: 설치된 Tailscale과 배포 package가 어떤 firewall 구현을 기대하는지 확인합니다. 해당 배포판의 호환 iptables package를 설치하거나 공식 package 설정으로 nftables를 선택해야 합니다.
  • binary는 있지만 실행이 실패: PATH, 실행 권한, iptables backend, container capability를 확인합니다. binary 존재만으로 rule 조작 권한이 증명되지는 않습니다.
  • 사용자 정의 rule 순서 때문에 통신이 깨짐: 구현 선택보다 netfilter mode와 rule order 문제일 수 있습니다. nodivert는 규칙을 만들지만 자동 연결하지 않으므로 수동 jump 또는 hook 구성이 필요합니다.

off를 빠른 해결책으로 사용하지 않는다

netfilter mode off에서는 Tailscale이 firewall 규칙을 만들거나 관리하지 않습니다. 공식 문서는 이 경우 tailscale0 traffic, Tailscale UDP listener, subnet routing과 exit node NAT에 필요한 규칙을 운영자가 책임져야 한다고 설명합니다. 연결이 잠깐 살아나는 것처럼 보여도 routing 기능과 spoofing 방어가 빠질 수 있습니다.

nodivert도 자동 해결은 아닙니다. iptables에서는 Tailscale chain으로 가는 jump를, nftables에서는 hook에 chain을 등록하는 작업을 직접 해야 합니다. 기존 firewall 관리 도구와 rule order를 통제해야 하는 명확한 요구가 없으면 기본 on을 유지합니다.

tailscale set --help
tailscale ping <PEER>

netfilter-mode 변경은 조회가 아닙니다. 현재의 on/nodivert/off 값과 서비스 환경·UCI 설정을 비공개로 기록하고 정상적인 별도 관리 경로를 확보한 경우에만 변경합니다. OpenWrt 옵션 이름은 설치 패키지의 설정 정의에서 확인해야 하며, 확인하지 않은 UCI 키를 추측하지 않습니다.

firewall 구현을 시험해야 할 때

Tailscale은 TS_DEBUG_FIREWALL_MODE 환경 변수를 iptables, nftables, auto 시험에 제공하지만 임시 수단이며 영구 지원으로 간주하지 말라고 명시합니다. Linux에서는 /etc/default/tailscaled를 백업하고 한 번에 한 구현만 시험합니다. OpenWrt package는 별도의 UCI 옵션을 제공할 수 있으므로 Linux 파일 경로를 그대로 복사하지 않습니다.

OpenWrt package issue 27740은 24.10.3과 Tailscale 1.80.3-1 조합의 iptables 오류 보고를 담고 있지만, 보고된 환경 하나가 모든 OpenWrt 설치의 원인을 증명하지는 않습니다. 현재 package version과 전체 fallback log를 먼저 비교해야 합니다.

검증과 되돌리기

수정 후에는 daemon online 상태뿐 아니라 peer 연결, subnet route 또는 exit node처럼 실제 사용하는 기능을 시험합니다. rule listing을 남겨 Tailscale chain이 생성되고 활성 경로에 연결됐는지 확인합니다. 운영 firewall manager를 reload한 뒤에도 결과가 유지되는지 봅니다.

새 firewall mode에서 daemon이 시작하지 않으면 이번에 바꾼 서비스 환경 또는 UCI 항목과 netfilter mode를 기록한 이전 값으로 복원합니다. 이전값이 nodivert/off였다면 on으로 고정하는 것은 원복이 아닙니다. package 설치·제거는 firmware와 feed 호환성을 확인한 별도 변경으로 처리합니다. 실제 OpenWrt 장치의 적용·복구는 이번에 재현하지 않았습니다.

공식 문서 및 확인 기준

이 글에 남아 있던 이전 검증 기록

검증 수준: 공식 문서 대조

Tailscale의 firewall 구현과 netfilter 관리 모드를 공식 문서로 분리했습니다. 공개 OpenWrt issue는 하나의 사례로만 사용했으며 특정 package version의 일반적 결함으로 확대하지 않았습니다.

작성 방식과 수정 정책 · 오류 제보