접속 수립 · 인증
피어 간 연결은 cluster_raft_self로 명시한 Raft 전용 주소에서 수립됩니다. TCP/TLS와 challenge- response 인증까지는 클라이언트 포트와 같지만, 인증 직후에는 Raft 전용 peer hello가 추가됩니다.
- TCP 접속 — 항상 부르는(dial) 쪽이 요청자가 됩니다
- 서버가 TLS를 켰다면 TLS 핸드셰이크
- 인증 핸드셰이크 1회 — 규격(challenge·digest·응답)은 클라이언트 포트와 바이트 단위로 동일합니다
- 고정 peer hello를 요청→응답 순서로 교환하고 identity와 wire version을 exact 검증
- 이후 길이-프리픽스 RPC 교환
peer hello
인증 성공 직후 아래 64바이트 고정 header와 두 UTF-8 가변 필드를 교환합니다. postcard와 OpenRaft 타입에 의존하지 않는 영구 envelope이며, 이 검증이 끝나기 전에는 RPC tag 1..4, 16을 허용하지 않습니다.
| 필드 | 크기 | 값/규칙 |
|---|---|---|
magic | 8 | ASCII TCKRAFT1 |
cluster_wire_version | u16 BE | 현재 1, exact match |
flags | u16 BE | 현재 0, 다른 값 거부 |
source_node_id | u64 BE | 보내는 process의 active NodeId |
target_node_id | u64 BE | 연결 대상의 active NodeId |
source_incarnation | u128 BE | 보내는 process의 고유 incarnation |
target_incarnation | u128 BE | 연결 대상의 고유 incarnation |
cluster_id_len | u16 BE | 1..128 |
server_version_len | u16 BE | 1..64 |
cluster_id | 가변 | 같은 fencing domain인지 exact 검증 |
server_version | 가변 | 관측용; 값이 달라도 이것만으로 거부하지 않음 |
전체 hello는 최대 256바이트입니다. dial 쪽이 먼저 보내고 accept 쪽이 source/target NodeId와 incarnation을 반대로 둔 같은 구조로 답합니다. magic, wire version, flags, cluster ID, source/target NodeId와 incarnation 중 하나라도 기대값과 다르면 즉시 연결을 닫습니다. SERVER_VERSION은 로그와 metric용일 뿐 호환 판단에는 사용하지 않습니다.
CLUSTER_WIRE_VERSION은 framing byte뿐 아니라 Grant/Expire/token/membership/snapshot의 복제 의미가 달라질 때도 올립니다. 서로 다른 wire version을 섞은 rolling upgrade는 지원하지 않으며, 호환되지 않는 변경은 lease drain 뒤 새 cluster_id로 배포합니다.
흐름
부르는 노드 (dial)
받는 노드
TCP 접속 (cluster_raft_self)
서버가 TLS를 켰다면 TLS 핸드셰이크
challenge (SHA-256 ␣ nonce)
digest — cluster_tokens의 첫 번째 토큰으로 계산
검증은 cluster_tokens 목록 전체로
peer hello — wire 1 · cluster/NodeId/incarnation
peer hello — source/target을 반대로 응답
이후 길이-프리픽스 Raft RPC 교환
요청응답합의 RPC (Raft)
클라이언트 포트와 다른 점
| 항목 | 클라이언트 포트 | Raft 포트 |
|---|---|---|
| 검증 토큰 집합 | client_tokens | cluster_tokens |
| 보내는 쪽 토큰 | 클라이언트가 설정한 토큰 | cluster_tokens의 첫 번째 토큰 |
| 인증 이후 | \n 종결 프레임 | peer hello 뒤 길이-프리픽스 RPC |
cluster_tokens는 비어 있지 않아야 하며 핸드셰이크에서 항상 검증합니다. 토큰 변경은 동일한CLUSTER_WIRE_VERSION과 replicated semantics를 유지한 상태에서 새 NodeId learner 교체 절차로 수행합니다 (설정 (환경변수)).- TLS가 켜져 있으면 Raft 포트도 같은 인증서를 씁니다. 피어를 부르는 쪽은 상대 인증서를
tls_ca(없으면 시스템 신뢰 저장소)로 검증하며,tls_skip_verify는 테스트 전용입니다. - 인증 실패 시
E auth_failed후 연결이 닫힙니다. peer hello의 mismatch·부분 전송·timeout도 응답 stream을 재사용하지 않고 닫습니다.