오늘 SingLinkVPN을 만드는 팀 SingLinkLabs가 SingLink 프로토콜의 전체 소스 코드를 Apache-2.0 라이선스로 GitHub에 공개했습니다. 이제 누구나 사양을 읽고, 코드를 실행하고, 보안을 검토하고, 그 위에 새로운 것을 만들 수 있습니다.
SingLinkVPN 오픈 소스 계획을 발표하면서 VPN 프로토콜과 VPN 클라이언트를 단계적으로 공개하겠다고 말씀드렸습니다. 이번 공개가 바로 그 단계입니다. 프로토콜은 그 위에서 동작하는 SingLinkVPN 앱 1세대 프로토타입과 함께 공개됩니다. 자세한 내용은 SingLinkVPN 앱 프로토타입 오픈 소스 공개 글을 참고하세요.
저장소: SingLinkLabs / singlink-protocol · 버전: 1.0.0-draft(와이어 이름
SingLink/1, 사양 초안 2판) · 라이선스: Apache-2.0 · 언어: Go, 표준 라이브러리만 사용
이번에 공개하는 것
사양서. SPEC.md는 와이어 포맷을 바이트 단위로 설명하므로, 누구나 이 프로토콜을 독립적으로 구현할 수 있습니다.
Go로 작성한 프로토콜 라이브러리. 암호 기능은 Go 표준 라이브러리만 사용하며, 서드파티 의존성이 전혀 없습니다.
명령줄 도구. 키 생성, 접속 패스 발급, 연결 링크 생성, 노드와 클라이언트 실행, 한 대의 컴퓨터에서 돌아가는 데모 실행을 지원합니다.
앱용 로컬 프록시(SOCKS5 및 HTTP)와 C 라이브러리 인터페이스(
libsinglink). 어떤 플랫폼의 앱이든 프로토콜을 내장할 수 있습니다.배포 예시. 노드 설정 샘플과 보안을 강화한 systemd 서비스 파일.
내부 보안 검토. 모든 발견 사항과 수정 내역을 SECURITY-AUDIT.md에 담았습니다.
SingLink 2.0과 SingLink 오픈 프로토콜은 서로 다른 프로토콜입니다
공식 SingLinkVPN 앱은 SingLink 2.0을 비롯한 당사의 프로덕션 프로토콜로 동작합니다. SingLink 2.0의 핵심 소스 코드는 이번 공개에 포함되지 않으며, 계속 비공개로 유지됩니다.
오늘 공개한 SingLink 프로토콜(SingLink 2.0과 구분해야 할 때는 'SingLink 오픈 프로토콜'이라고 부릅니다)은 SingLinkLabs가 개방형 개발을 위해 처음부터 새로 설계한 별개의 프로토콜입니다. 현재 공식 앱은 이 프로토콜을 사용하지 않습니다. 기존 사용자에게는 달라지는 것이 없습니다. 앱도, 계정도, 연결도 그대로입니다.
오픈 소스로 공개하는 이유
보안 주장은 검증할 수 있어야 합니다. 양자 내성 키 교환, 기기 바인딩, 탐지 저항성은 말로 내세우기는 쉽습니다. 코드와 사양이 공개되어 있으면 누구나 직접 확인할 수 있습니다.
보는 눈이 많을수록 문제를 빨리 찾습니다. 외부 연구자와 엔지니어는 내부 팀이 놓친 문제를 발견할 것입니다.
다른 사람들이 그 위에 만들 수 있습니다. 개발자는 테스트하고, 자신의 프로젝트에 내장하고, 개선을 제안할 수 있습니다.
약속한 계획을 지키는 일입니다. 프로토콜 공개는 저희가 약속한 단계 중 하나였습니다.
쉽게 풀어 본 작동 방식
한 문장으로 요약하면, 밖에서 보기에 사용자는 평범한 HTTPS 웹사이트에 접속하고 있을 뿐입니다. 그 안에 암호화된 접속 요청이 숨어 있고, 서버는 유효한 패스를 가진 사람의 트래픽만 중계합니다.
이 설계에는 세 가지 키가 쓰입니다. 사무실 건물의 보안에 비유해 보겠습니다.
노드 키는 문 자물쇠입니다. 서버마다 고유한 키가 있습니다. 사용자의 요청은 해당 서버만 열 수 있으며, 이를 통해 사용자가 진짜 서버에 도달했다는 사실도 증명됩니다.
발급자 키는 인사팀의 직인입니다. 계정 백엔드에 보관되며, 각 접속 패스에 요금제, 만료일, 속도 제한, 기기 수 제한을 적어 직인을 찍습니다.
기기 키는 사용자의 지문입니다. 사용자의 휴대폰이나 컴퓨터에 보관되며, 모든 연결에 서명해 패스를 정당한 소유자가 사용하고 있음을 증명합니다.
서버는 직인이 어떻게 생겼는지만 알면 스스로 패스를 확인할 수 있습니다. 그래서 노드는 사용자 데이터베이스를 두지 않으며, 사용자 데이터도 저장하지 않습니다.
한 번의 연결에서 일어나는 일
앱이 어떤 웹사이트로 향하는 평범한 HTTPS 연결처럼 보이는 연결을 엽니다.
첫 번째 패킷에는 이 연결에만 쓰는 일회용 키, 양자 내성 암호문, 그리고 봉인된 영역이 담깁니다. 봉인된 영역에는 목적지, 접속 패스, 실제 데이터의 앞부분 최대 8 KB, 요청 전체에 대한 기기 서명이 들어 있습니다. 추가 왕복 통신은 필요하지 않습니다.
서버는 모든 것을 확인합니다. 요청을 복호화할 수 있는지, 직인이 진짜인지, 기기 서명이 일치하는지, 시각이 맞는지, 그리고 요청이 재전송된 것이 아니며 만료되거나 취소되지 않았는지 확인합니다.
모든 확인을 통과해야만 응답하고 중계를 시작합니다. 하나라도 실패하면 연결은 손대지 않은 채 실제 웹사이트로 넘겨집니다. 서버를 탐지하려는 사람에게는 평범한 웹사이트만 보이며, 응답 시간에도 차이가 없습니다.
양쪽은 각자의 일회용 키를 결합해 이 연결의 세션 키를 만듭니다. 데이터는 청크 단위로 암호화되고, 처음 몇 개의 청크에는 패딩이 추가되며, 일정량을 사용하면 키가 자동으로 교체됩니다.
보안 특성
이중 암호화. 바깥쪽 HTTPS에 더해 안쪽에 프로토콜 자체의 AES-256-GCM 계층이 있어, HTTPS를 종료하는 CDN조차 내용을 볼 수 없습니다.
양자 내성 보호. 키 교환은 기존의 X25519와 ML-KEM-768(FIPS 203)을 결합합니다. 공격자는 둘 다 깨뜨려야 합니다.
전방 비밀성. 연결마다 일회용 키를 사용하므로, 나중에 서버가 침해되더라도 과거 트래픽을 복호화할 수 없습니다. 단, 첫 번째 패킷은 예외입니다(아래 한계 참고).
기기 바인딩. 어딘가에서 복사한 접속 패스는 발급 대상 기기의 키가 없으면 쓸모가 없습니다.
재전송 방지. 가로챈 패킷을 다시 보내도 통하지 않으며, 서버를 재시작한 뒤에도 마찬가지입니다.
탐지 저항성. 만료되었거나, 취소되었거나, 재전송되었거나, 위조된 요청은 모두 똑같이 처리되어 실제 웹사이트로 넘겨집니다.
중앙 제어. 계정이나 기기를 취소하면 모든 서버에서 진행 중인 연결이 약 10초 안에 종료됩니다.
강화된 서버. 서버별·IP별 연결 수 제한, 핸드셰이크용 CPU 예산, 사설 주소와 특수 용도 주소를 빠짐없이 막는 차단 목록을 갖추고 있습니다.
설계 아이디어의 출처
SingLink 프로토콜은 검증된 설계에서 배웠습니다. VLESS와 Trojan의 단일 요청 연결, Trojan과 obfs4의 실패한 연결을 실제 웹사이트로 넘기는 방식, Noise NK 핸드셰이크 패턴, TLS 1.3의 키 유도와 0-RTT 처리, X-Wing 표준 초안의 하이브리드 양자 내성 키 교환, Shadowsocks AEAD의 청크 암호화, JWT와 PASETO의 서명 토큰, OAuth DPoP의 기기 바인딩 토큰, HAProxy PROXY protocol, 그리고 WireGuard의 재전송 방지와 부하 방어가 그것입니다.
참고한 것은 설계 아이디어뿐입니다. 모든 코드는 처음부터 새로 작성했습니다. Xray, V2Ray, sing-box, WireGuard의 코드는 전혀 포함되어 있지 않습니다.
현재 상태와 알려진 한계
아직 초안입니다. 버전은 1.0.0-draft이며, 와이어 포맷은 앞으로 바뀔 수 있습니다.
지금까지는 내부 보안 검토만 거쳤습니다. 검토자 2명이 암호 설계와 구현을 각각 따로 검토해 31건의 발견 사항을 기록했습니다. High 2건, Medium 14건이며, 나머지는 Low 또는 참고 수준입니다. 사용자 트래픽의 기밀성이나 인증을 깨뜨린 항목은 없었습니다. High와 Medium 항목은 모두 수정되거나 완화되었고, 항목마다 회귀 테스트가 있으며, 모든 파서는 퍼즈 테스트로 검증됩니다.
아직 제3자 감사를 받지 않았습니다. 독립적인 감사를 받기 전까지는 위험도가 높은 용도에 이 프로토콜을 의존하지 않기를 권장합니다. 안정 버전이라고 부르기 전에 감사를 받을 계획입니다.
첫 번째 패킷은 전방 비밀성을 갖지 않습니다. 서버의 장기 키로 보호되므로, 서버 키는 정기적으로 교체해야 합니다. 키 교체는 지원됩니다.
중국 본토에서 실전 테스트를 거치지 않았습니다. TLS 지문과 첫 번째 패킷의 크기는 아직 구별될 수 있습니다. 중국 본토 사용자를 위해 공식 SingLinkVPN 앱은 계속 기존 프로덕션 프로토콜을 사용합니다.
서버에는 자체 도메인이 필요하며, 브라우저가 신뢰하는 인증서와 그 뒤에서 동작하는 실제 웹사이트도 있어야 합니다.
직접 사용해 보고 참여하기
Go 1.24 이상이 있다면 make test로 테스트 스위트를 실행하고, make cli로 명령줄 도구를 빌드하고, singlink demo로 한 대의 컴퓨터에서 로컬 서버와 클라이언트를 시작할 수 있습니다. 서버 운영 방법은 저장소의 README에 설명되어 있습니다.
질문, 버그 제보, Pull Request는 GitHub에서 언제든 환영합니다. 보안 취약점은 공개 Issue가 아닌 비공개로 제보해 주세요. 절차는 SECURITY.md에 안내되어 있습니다.
라이선스와 상표
코드는 Apache-2.0 라이선스로 제공됩니다. 라이선스 조건에 따라 상업적 용도를 포함해 사용, 수정, 재배포할 수 있습니다. "SingLink"와 "SingLinkVPN"이라는 이름과 로고는 SingLinkLabs의 상표이며, 라이선스는 저작물의 출처를 설명하는 범위를 넘어 이를 사용할 권한을 부여하지 않습니다. 수정 버전과 포크는 고유한 이름과 아이콘으로 공개해야 합니다.
더 읽어 보기
SingLinkVPN 앱 프로토타입 오픈 소스 공개: 코드는 GitHub에서 확인할 수 있습니다
SingLink 2.0 기술 백서: 공식 앱의 프로덕션 프로토콜
