네 가지 확인이 동작하는 마크 규칙과 동작하는 경로를 구분한다. 규칙이 어떤 마크를 읽는지, 조회 시점에 패킷이 아직 그것을 지니고 있는지, 이후 패킷에 연결 마크가 복원되었는지, 그리고 해당 규칙의 마스크와 우선순위가 그것을 발동시키도록 허용하는지. 증가하는 카운터는 어떤 규칙이 무언가와 일치했다는 것만 증명한다. 커널이 경로를 선택할 때 패킷이 무엇을 지녔는지에 대해서는 아무것도 말하지 않는다.

두 마크는 서로 다른 곳에 살고 서로 다른 일정에 따라 만료된다.

두 마크, 두 수명

패킷 마크는 하나의 skb에 속하고, 그와 함께 훅을 통과하며, 정책 라우팅의 fwmark 선택자에 의해 소비된다. 연결 마크는 conntrack 항목에 속하고, 그 흐름의 패킷 전반에 걸쳐 남아 있으며, 무언가가 다시 복사할 때까지 라우팅 규칙에는 보이지 않는다. 패킷 마크를 연결에 저장하는 것은 저장이고, 복원하는 것은 별개의 동작이다. 둘 다 암묵적으로 일어나지 않는다.

그래서 규칙 집합은 일관돼 보이는데 라우팅 결정은 제로를 보는 일이 생긴다. 값은 저장되었고 아무것도 그것을 복원하지 않았다.

둘 사이의 복사는 당신이 작성하는 단계다

중요한 두 문장은 반대 방향으로 간다. 하나는 패킷의 마크를 연결에 저장하고, 다른 하나는 연결의 마크를 패킷에 적재한다. 어느 쪽이 필요한지는 흐름에 대한 분류 시점에 달려 있다. 설계가 패킷 마크만 필요할 수도 있고, 어떤 우회책이 둘 다 사용했다고 해서 conntrack 마킹을 추가하는 것은 단순한 정책이 두 번째 실패 모드를 얻는 방식이다.

ct mark set meta mark
meta mark set ct mark

규칙 옆에 방향을 적어 두어라. 언뜻 보아 문법만으로는 명확하지 않기 때문이다. 첫 줄은 저장하고, 둘째 줄은 복원하며, 어느 것도 다른 것을 함축하지 않는다.

그것을 소비하는 조회보다 먼저 분류하라

로컬에서 생성된 트래픽과 LAN에서 전달된 트래픽은 서로 다른 훅을 지나 서로 다른 시점에 라우팅 결정에 도달한다. 라우터 자체의 연결에 동작하는 출력 규칙은 전달된 클라이언트의 패킷이 조회 전에 마크되었다는 것을 증명하지 않는다. 분류를 그것을 소비하는 조회가 아직 일어나지 않은 곳에 두고, 같은 체인의 이후 규칙이 값을 덮어쓰는지 확인하라. 체인 내부의 순서는 구성의 일부이며 구현 세부 사항이 아니다.

연결 상태의 지속성에도 명시적인 계획이 필요하다. 흐름의 첫 패킷만 분류된다면 이후 패킷은 저장된 마크의 복원이 필요하고, 그렇지 않으면 마크가 없는 경로를 택한다. 연결을 설명하는 마크와 패킷을 설명하는 마크의 차이가 바로 이것이다.

경로에 마크가 붙은 질문을 하라

ip route get 10.77.0.10 mark 0x2

규칙과 테이블을 살펴본 뒤 마크를 포함해 경로에 질의하고, 정책에 영향을 준다면 출발지나 수신 인터페이스도 더하라. 마크 없는 평범한 조회는 다른 질문에 답하며 원하지 않던 경로를 기꺼이 알려 줄 것이다. 규칙의 값뿐 아니라 마스크와 우선순위도 확인하고, 선택된 테이블에 사용 가능한 경로가 있는지 확정하라.

증가하는 카운터는 어떤 규칙이 어떤 패킷과 일치했다는 증거다. 최종 패킷이 올바른 결정 지점에서 의도한 마크를 지녔다는 증거는 아니다.

마크, 방향, 시점, 마스크를 읽어라. 네 가지 확인이면 경로는 더 이상 수수께끼가 아니다.

관련 글