요약

  • 프록시는 기존 동일 유형 값 뒤에 자신의 비공개 Proxy-State 값을 하나 추가하고, 응답이 되돌아오면 자신의 것을 제거할 수 있었다. 다른 프록시들은 이전 값들과 그 상대적 순서를 그 내용을 지시문으로 취급하지 않고 보존해야 했다.
  • 이 규칙은 패킷 끝에 연속된 블록이 있을 것을 요구하지 않았고, 모든 이전 값이 최종 서버까지 전달되어야 한다는 요구조차 없었다. 프록시는 자신의 클라이언트에 보내는 응답에서 해당 값들을 복원한다면 수신한 값을 로컬에 보관할 수 있었다.
  • 상태를 반환하는 것, 접근 정책을 적용하는 것, 인접 서버를 인증하는 것은 서로 다른 약속이었다. 불투명한 값도 보호된 연결도 연쇄 전체의 모든 결정에 대한 신뢰를 확립하지 못했다.

마지막 라벨이 반드시 마지막 속성일 필요는 없다

두 개의 Proxy-State 속성 사이에 다른 유형의 속성이 하나 끼어 있는 RADIUS 요청을 생각해 보자. 모든 비공개 라벨이 패킷 끝에 함께 놓여 있다고 기대하는 수신자는 이 배열을 마음에 들어 하지 않을 수 있다. 2000년 6월에 정해진 규칙에서는 그러한 선호만으로는 이를 거부할 근거가 되지 못했다.

RFC 2865는 프록시가 동일 유형 속성의 순서를 보존하도록 요구했다. 서로 다른 유형 사이에 고정된 순서를 부과하지는 않았으며, 수신자는 반복 속성이 연속적이기를 강요할 수 없었다. 자신의 Proxy-State를 추가하는 프록시는 이를 이전 Proxy-State 값들 뒤에 넣었다. 그 뒤에 다른 유형의 속성이 이어질 수도 있었다.

이것은 지저분한 서식에 대한 사소한 양보가 아니었다. 어느 관계가 의미를 갖는지를 정확히 명시한 것이다. 마지막 Proxy-State는 가장 마지막에 값을 추가한 프록시에 속했고, 그 순서에서 마지막이라는 것은 패킷에서 마지막이라는 뜻이 아니었다. 공유된 규칙은 모든 구현의 선호 배열을 강요하지 않으면서 소유권을 보존했다.

이 예시는 사양에 대한 해석이며, 재구성된 장애 사례가 아니다. 구현 관행을 구현들 간의 합의보다 강하게 만드는 것의 위험을 보여준다. 프로토콜은 중요한 순서에 대해서는 정밀하면서 다른 순서 선택은 열어 둘 수 있었다.

하나의 중개자, 두 개의 대화

전형적인 RADIUS 교환에서 네트워크 접속 서버가 클라이언트였다. 접속을 구하는 사람은 사용자라는 이유만으로 그 교환에서 RADIUS 클라이언트가 아니었다. 접속 장비가 서버에 요청을 보내고, 서버는 인증 영역을 포함한 자신의 구성에 따라 그것을 처리하거나 다른 서버로 전달할 수 있었다.

전달 기계는 이전 참여자에게는 서버이고 다음 참여자에게는 클라이언트였다. 어떤 영역에서는 최종 서버가 될 수 있고 다른 영역에서는 프록시일 수 있었다. 여러 전달 서버가 연쇄를 이룰 수 있었다. 루프를 피하는 일은 여전히 필요했고, Proxy-State는 연쇄를 그 자체로 올바르게 만들어 주는 라우팅 알고리즘을 제공하지 않았다.

1999년 6월의 Informational 문서RFC 2607은 네트워크 간 로밍을 위해 이 배열을 검토했다. 프록시는 관계를 단순화하고, 상이한 기능 수준을 수용하고, 정책을 적용하고, 계정 트래픽을 처리할 수 있었다. 접속 지점과 인증 결정을 내리는 조직이 같은 곳일 필요가 없어졌다.

그러나 이 문서는 당시의 보안 가정이 공개 인터넷 전반의 배포에는 부적합하다고 경고했다. 하나의 관리 도메인 내부의 신뢰가 독립된 조직들 사이의 이동을 통해 자동으로 유지되지 않았다. 당시 배포 상황에 대한 이 서술을 오늘날의 도입 통계로도, 이 아키텍처의 안전성에 대한 전면적 보증으로도 바꾸어 읽어서는 안 된다.

공개 처리 규칙을 갖는 비공개 값

Proxy-State는 이미 1997년 4월의RFC 2138에 존재했다. 2000년 개정판은 프록시 동작과 속성 순서에 대해 더 충분한 설명을 담았다. 전달 서버는 자신의 Proxy-State 값을 하나 추가할 수 있었으나 하나보다 많이는 추가할 수 없었다. 값을 추가하는 것은 선택 사항이었고, 모든 프록시가 반드시 해야 하는 일이 아니었다.

이전 프록시들이 제공한 값은 불투명 데이터로 취급되어야 했다. 전달 서버의 프로토콜 동작은 그 비공개 내용에 의존할 수 없었다. 실제 형식과 사용 방식은 그 값을 만들어 낸 사이트나 애플리케이션에 맡겨져 있었다.

이 구분은 의도적인 것이었다. 중개자는 속성의 경계를 인식하고 바이트를 보존할 필요는 있었지만, 모든 다른 중개자의 내부 상태에 대한 공통 정의를 가질 필요는 없었다. 참여자들은 값 안의 모든 의미를 공유하지 않고도 값을 다루는 규칙을 공유했다.

최종 서버에서는 수신한 Proxy-State 값들이 변경 없이 순서대로 응답에 복사되었다. 이 의무는 Access-Accept, Access-Reject, Access-Challenge 모두에 적용되었다. 거부라도 중개자들이 자신들의 작업을 완료하는 데 필요한 정보를 되돌려 주어야 했다. 값이 안전하게 반환되었다는 것은 사용자에게 접속이 허가되었다는 증거가 아니었다.

되돌아가는 경로에서, 자신의 값을 추가했던 프록시는 마지막 Proxy-State, 즉 자신의 것을 제거했다. 이전 값들은 이전 프록시들을 위해 남아 있었다. 아무것도 추가하지 않은 서버는 이제 응답을 전달하는 중이라는 이유만으로 다른 사람의 값을 제거할 권리가 없었다.

스택에 비유하는 것은 이 한계 안에서만 유용하다. 이는 소유자들이 역순으로 자신의 정보를 되찾는 과정을 설명한다. 패킷 물리적 끝에 의무적인 연속 스택이 존재한다든가, 완전한 경로 기록이라든가, 라벨 자체에 대한 공유 언어를 확립해 주지는 않는다.

완전한 경로 이력을 배제하는 예외

Proxy-State를 요청이 방문한 모든 지점의 기록으로 오해해서는 안 되는 또 다른 이유가 있었다. 전달 서버는 자신이 다음으로 보내는 요청에서 이전에 수신한 Proxy-State 값들을 생략할 수 있었다. 그렇게 한다면 자신의 클라이언트에 응답을 반환하기 전에 그 값들을 응답에 다시 붙여야 했다.

다시 말해, 전달 서버는 다른 참여자의 상태를 최종 서버까지 끌고 가는 대신 로컬에 보관함으로써 그 상태를 보존할 수 있었다. 나가는 패킷에는 이전 상태의 일부만 담길 수 있었지만, 최종적으로 되돌아오는 응답은 여전히 이전 참여자의 기대를 충족했다.

이는 트레이스를 검토하는 사람에게 중요하다. 다음 연결에서 값이 없다는 것 자체는 손실의 증거가 아니다. 값이 소유자에게 반환되었다는 것도 홈 서버가 그것을 보았다는 증거가 아니다. 관련 비교는 약속이 이루어진 인터페이스에서 이루어진다: 프록시가 자신의 클라이언트로부터 받은 것과 그 클라이언트에게 반환한 것이다.

이 선택은 작업을 제거한 것이 아니라 옮긴 것이었다. 값을 로컬에 보관한 프록시는 응답이 도착했을 때 그것을 회복해야 했다. 사양은 그 저장 방식을 정하지 않았다. 다만 외부에서 볼 수 있는 결과를 요구했다. 로컬 구현의 자유에는 교환을 끝마칠 만큼 기억할 지역적 의무가 따랐다.

불투명하다고 암호화된 것은 아니었다

Proxy-State는 정의된 속성 길이를 갖는 이진 데이터였고, 미적 개선을 기다리는 텍스트 필드가 아니었다. 그 값은 0 옥텟을 포함할 수 있었다. 그 0을 문자열 종료 문자로 취급하는 프로그램은 원래 구현이 여전히 필요로 하는 정보를 잘라 버렸을 것이다.

공백을 잘라 내거나, 대소문자를 바꾸거나, 겉보기 문자열을 정규화하는 것도 똑같이 잘못된 행위였다. 프록시는 다른 구현의 비공개 표현을 편집하는 편집자가 아니었다. 값을 식별하는 방법을 안다는 것은 그 내용을 개선할 권리를 주지 않았다.

그러나 불투명성은 마법적인 기밀성을 제공하지 않았다. 불투명성은 참여자가 어떻게 값을 해석하지 말아야 하는지를 기술하는 것이지, 그 참여자가 값을 보지 못하게 하는 암호학적 장벽이 아니었다. 악의적인 중개자가 데이터를 복사하거나 변경할 물리적 능력은, 준수하는 중개자에게 행동 방식을 알려 주는 규칙으로 인해 사라지지 않았다.

IANA RADIUS 속성 레지스트리는 State, Class, Proxy-State의 공통 식별자를 제공한다: 유형 24, 25, 33. 그러한 레지스트리는 공유 속성 공간을 식별한다. 모든 비공개 인코딩을 기술하거나, 실제 프록시가 값을 올바르게 반환했다는 것을 증명하거나, 어떤 조직이 특정 사용자에게 접속을 허가할 수 있는지 결정하지는 않는다.

상태가 하나의 무차별적인 것은 아니었다

상태에 관련된 세 가지 속성은 서로 다른 수명을 따랐다. State는 Access-Challenge의 서버 정보를 다음 Access-Request로 옮겨 인증 대화가 계속되도록 도울 수 있었다. Class는 Access-Accept와 함께 계정 트래픽으로 갈 수 있었고, 기본 사양은 계정 기능이 지원될 때 그것을 변경 없이 운반하도록 권고했다. Proxy-State는 전달 중개자의 반환 경로에 사용되며 그 중개자가 제거했다.

2007년 12월의RFC 5080은 새로운 또는 재시작된 인증 요청이 사용자와 포트가 동일하다는 이유만으로 이전 대화의 State를 재사용해서는 안 된다는 점을 명확히 했다. 사람이나 접속 지점의 동일성이 대화의 연속성을 확립하지는 않았다.

모든 불투명 필드를 일반 세션 식별자로 취급하면 이러한 차이가 가려진다. 그 결과 시스템이 그 의미를 부여한 교환을 넘어 값을 보관하거나, 의도된 사용 전에 제거하거나, 생산자가 약속한 것보다 강한 관계를 추론할 수 있다.

계정 기능은 유한한 약속의 별개 사례를 제공했다. 2000년 6월의 Informational 문서RFC 2866에서 Accounting-Response는 요청을 수신하고 성공적으로 기록한 뒤에 이어졌다. 이는 패킷이 네트워크 인터페이스에 도달했다는 표시에 불과한 것이 아니었다.

그러나 중개자는 원격 응답을 기다릴 수도 있고, 로밍 논의가 탐구했듯이 로컬 저장과 이후 전달을 책임질 수도 있었다. 한 참여자의 확인이 반드시 모든 다른 조직이 이미 같은 사건을 기록했다는 뜻은 아니었다. 영수증을 이해하려면 누가 발행했는지, 그 참여자가 어떤 작업을 떠맡았는지를 알아야 했다.

패킷 안의 정책 경계

프록시는 로컬 정책을 집행하기 위해 일부 속성을 수정할 수 있었다. 그럼에도 RFC 2865는 기존의 Proxy-State, State, Class 값의 수정을 보호했다. 메시지가 전적으로 불변인 것은 아니었고, 정책에 맞춘 조정이 반드시 악의적인 것도 아니었다. 금지는 다른 참여자에게 그 보존이 중요한 특정 정보에 관한 것이었다.

원래의 응답 처리도 이웃 사이에서 작동했다. 프록시는 원격 서버와의 시크릿을 사용해 응답 인증자를 검사하고, 실패한 응답을 폐기하고, 자신의 클라이언트의 원래 요청에 대한 Identifier를 복원하고, 그 클라이언트를 위한 응답 인증자를 계산했다. 동일한 인증된 봉투가 모든 관리 경계를 넘어 그대로 유지되지는 않았다.

RFC 2607의 보안 논의는 의도된 동작과 악의적인 프록시가 그것을 위반할 가능성을 구분했다. 유리한 결정을 만들어 내는 것에 대한 금지 규칙 자체가 그러한 조작을 불가능하게 만드는 종단 간 메커니즘은 아니었다. 기술적 능력, 허용된 프로토콜 동작, 다른 조직에 대한 정당한 권위는 서로 다른 주장이었다.

2012년 5월의 Experimental 문서RFC 6614는 메시지를 처리할 수 있는 중개자를 유지하면서 RADIUS를 TLS 위에서 운반하도록 했다. 2025년에 발표된 ExperimentalRADIUS/1.1 프로파일은 관련 TLS 및 DTLS 연결의 보호를 더 변화시켰다. 어느 발전도 모든 중개자를 사라지게 하지 않았고, 비공개 반환 상태를 정책 충실성에 대한 종단 간 증거로 바꾸지도 않았다.

이전의 공유 시크릿과 MD5 절차는 현재 배포 조언이 아니라 역사로서 여기에 기술되어 있다. 새로운 전송 사양 역시 보편적 도입을 증명하지 않는다. 각 보호된 관계는 실제로 시작하고 끝나는 지점에서 이해되어야 한다.

Proxy-State가 이룬 것은 보편적 신뢰보다 좁았다. 그것은 서로 다른 구현들이 각자의 비공개 기억에 대한 공통 해석 없이도 지킬 수 있을 만큼 정밀한 반환 의무를 만들었다. 라벨은 특정한 한 조각의 작업에 속했다. 그것을 운반하는 것은 대화 전체를 지시할 면허가 아니었다.