SOCKS5
읽기에 앞서
본 문서는 SOCKS5의 Protocol에 관해 기술합니다. 독자 분께서 이미 일반적인 개념에 대해서는 이미 알고 계신다고 가정하므로, 필요하다면 다른 문서, 위키피디아 등을 참고하세요.
UDP Protocol에 관한 내용은 다소 생략되어 있을 수 있습니다.
자세한 내용은 SOCKS5 위키피디아 혹은 SOCKS5의 일반적인 프로토콜에 관해 서술하는 RFC1928 및 Username/Password 인증에 관해 서술하는 RFC1929를 참고하세요.
Protocol 개요
SOCKS5 Protocol은 무척 간단합니다.
- 제일 먼저 클라이언트 측에서 인증 정보를 포함한 첫 메세지를 보내고
- 응답을 받고
- 인증을 하고
- 목표 서버의 정보를 보내고
- 응답을 받으면 끝입니다.
첫 번째 통신
클라이언트
| VER | NMETHODS | METHODS |
|---|---|---|
| 1 byte | 1 byte | 1 to 255 byte |
첫 메세지는 위와 같이 크게 세 부분으로 구분됩니다. SOCKS5 버전을 나타내는 VER, METHODS의 길이를 나타내는 NMETHODS, 그리고 METHODS죠.
우선 제일 먼저, VER은 0x05여야 합니다(SOCKS'5’).
NMETHODS는 클라이언트가 지원하는 인증 방법의 개수이지만, 보통은 0x01로 설정합니다. SOCKS5 서버에 요청 할 때에 보통 클라이언트는 인증 방법을 이미 알고 있으니까요.
METHODS는 인증 방법을 나열합니다. 인증 방법의 종류는 다음과 같습니다.
0x00NO AUTHNICATION REQUIRED0x01GSSAPI0x02USERNAME/PASSWORD0x03to0x7FIANA ASSIGNED0x80to0xFERESERVED FOR PRIVATE METHODS0xFFNO ACCEPTABLE METHODS
Example: 0x05 | 0x01 | 0x00
서버
서버는 클라이언트가 제시한 인증 방법들 중 하나를 골라 메세지를 전송합니다.
| VER | METHOD |
|---|---|
| 1 byte | 1 byte |
위의 클라이언트와 같이 VER은 0x05이고, METHOD 역시 위에 나열되어 있습니다.
Example: 0x05 | 0x00
인증
클라이언트
클라이언트가 USERNAME/PASSWORD(0x02)를 선택했다면, 인증을 위해 다음 형태의 메세지를 전송합니다.
| VER | ULEN | UNAME | PLEN | PASSWD |
|---|---|---|---|---|
| 1 byte | 1 byte | 1 to 255 byte | 1 byte | 1 to 255 byte |
VER은 RFC1929에 따라 0x01여야 합니다.
ULEN과 PLEN은 그 이름에서 예상할 수 있듯, Username과 Password의 길이를 의미합니다.
UNAME과 PASSWD는 그 Username과 Password입니다.
Example: 0x01 | 0x08 | 0x75 0x73 0x65 0x72 0x6E 0x61 0x6D 0x65 | 0x08 | 0x70 0x61 0x73 0x73 0x77 0x6F 0x72 0x64
서버
서버는 클라이언트의 해당 메세지의 인증을 점검 후 다음 메세지를 송신합니다.
| VER | STATUS |
|---|---|
| 1 byte | 1 byte |
VER은 0x01이며, 인증을 통과할 경우 0x00. 실패했을 경우 그 외의 값입니다.
Example: 0x01 | 0x00
두 번째 통신
클라이언트
이제 클라이언트는 본격적인 Tunneling을 요청합니다.
| VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
|---|---|---|---|---|---|
| 1 byte | 1 byte | 1 byte | 1 byte | Variable | 2 byte |
VER은 0x05입니다.
CMD는 Command, 원하는 명령을 선택해야 합니다. 종류는 다음과 같습니다.
- CONNECT
0x01 - BIND
0x02 - UDP ASSOCIATE
0x03
일반적으로는 0x01이 사용됩니다. 자세한 내용은 부록에서 소개합니다.
RSV는 미리 예약된 값 0x00입니다.
ATYP는 Address Type, 목표 주소의 종류인데, 다음으로 이루어집니다.
- IP V4 address:
0x01 - DOMAINNAME:
0x03 - IP V6 address:
0x04
DST.ADDR은 ATYP에 따라 그 구조가 다른데,
- 0x01, IPV4의 경우 4 byte 주소입니다.
- 0x03, DOMAINNAME의 경우 처음에 길이를 나타내는 1 byte가 온 뒤 도메인 주소가 옵니다.
- 0x04, IPv6의 경우 16 byte 주소입니다.
DST.PORT는 2 byte이므로 네트워크 바이트 오더, 빅 엔디안을 따르는 포트 번호입니다.
Example: 0x05 | 0x01 | 0x00 | 0x01 | 0x7f 0x00 0x00 0x01 | 0x38 0x04
CONNECT의 경우 서버
| VER | REP | RSV | ATYP | DST.ADDR | DST.PORT |
|---|---|---|---|---|---|
| 1 byte | 1 byte | 1 byte | 1 byte | Variable | 2 byte |
REP를 제외하고는 전부 위의 클라이언트와 동일합니다.
REP는 Reply field인데, 다음과 같은 값이 옵니다.
0x00succeeded0x01general SOCKS server failure0x02connection not allowed by ruleset0x03Network unreachable0x04Host unreachable0x05Connection refused0x06TTL expired0x07Command not supported0x08Address type not supported0x09to0xffunassigned
이후 서버와의 연결은 그대로 TCP Tunnel로서 작동합니다.
부록
CONNECT
TCP Tunnel을 형성합니다.
BIND
클라이언트가 서버의 연결을 수락해야 합니다. FTP 등의 Protocol에서 사용되며, BIND 과정에서 두 개의 응답이 전송되는데 첫 번째 응답은 새로운 소켓을 바인드 했을 때. 그리고 두 번째 응답은 연결이 성공하거나 실패했을때 전송됩니다.
UDP ASSOCIATE
UDP ASSOCIATE의 경우 응답 DST.ADDR과 DST.PORT가 클라이언트가 UDP 송신에 사용할 주소가 됩니다. 이때, TCP 연결은 계속 유지해야 합니다.