SOCKS5

읽기에 앞서

본 문서는 SOCKS5의 Protocol에 관해 기술합니다. 독자 분께서 이미 일반적인 개념에 대해서는 이미 알고 계신다고 가정하므로, 필요하다면 다른 문서, 위키피디아 등을 참고하세요.

UDP Protocol에 관한 내용은 다소 생략되어 있을 수 있습니다.

자세한 내용은 SOCKS5 위키피디아 혹은 SOCKS5의 일반적인 프로토콜에 관해 서술하는 RFC1928 및 Username/Password 인증에 관해 서술하는 RFC1929를 참고하세요.

Protocol 개요

SOCKS5 Protocol은 무척 간단합니다.

  1. 제일 먼저 클라이언트 측에서 인증 정보를 포함한 첫 메세지를 보내고
  2. 응답을 받고
  3. 인증을 하고
  4. 목표 서버의 정보를 보내고
  5. 응답을 받으면 끝입니다.

첫 번째 통신

클라이언트

VERNMETHODSMETHODS
1 byte1 byte1 to 255 byte

첫 메세지는 위와 같이 크게 세 부분으로 구분됩니다. SOCKS5 버전을 나타내는 VER, METHODS의 길이를 나타내는 NMETHODS, 그리고 METHODS죠.

우선 제일 먼저, VER은 0x05여야 합니다(SOCKS'5’).

NMETHODS는 클라이언트가 지원하는 인증 방법의 개수이지만, 보통은 0x01로 설정합니다. SOCKS5 서버에 요청 할 때에 보통 클라이언트는 인증 방법을 이미 알고 있으니까요.

METHODS는 인증 방법을 나열합니다. 인증 방법의 종류는 다음과 같습니다.

  1. 0x00 NO AUTHNICATION REQUIRED
  2. 0x01 GSSAPI
  3. 0x02 USERNAME/PASSWORD
  4. 0x03 to 0x7F IANA ASSIGNED
  5. 0x80 to 0xFE RESERVED FOR PRIVATE METHODS
  6. 0xFF NO ACCEPTABLE METHODS

Example: 0x05 | 0x01 | 0x00

서버

서버는 클라이언트가 제시한 인증 방법들 중 하나를 골라 메세지를 전송합니다.

VERMETHOD
1 byte1 byte

위의 클라이언트와 같이 VER은 0x05이고, METHOD 역시 위에 나열되어 있습니다.

Example: 0x05 | 0x00

인증

클라이언트

클라이언트가 USERNAME/PASSWORD(0x02)를 선택했다면, 인증을 위해 다음 형태의 메세지를 전송합니다.

VERULENUNAMEPLENPASSWD
1 byte1 byte1 to 255 byte1 byte1 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

서버

서버는 클라이언트의 해당 메세지의 인증을 점검 후 다음 메세지를 송신합니다.

VERSTATUS
1 byte1 byte

VER은 0x01이며, 인증을 통과할 경우 0x00. 실패했을 경우 그 외의 값입니다.

Example: 0x01 | 0x00

두 번째 통신

클라이언트

이제 클라이언트는 본격적인 Tunneling을 요청합니다.

VERCMDRSVATYPDST.ADDRDST.PORT
1 byte1 byte1 byte1 byteVariable2 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의 경우 서버

VERREPRSVATYPDST.ADDRDST.PORT
1 byte1 byte1 byte1 byteVariable2 byte

REP를 제외하고는 전부 위의 클라이언트와 동일합니다.

REP는 Reply field인데, 다음과 같은 값이 옵니다.

  • 0x00 succeeded
  • 0x01 general SOCKS server failure
  • 0x02 connection not allowed by ruleset
  • 0x03 Network unreachable
  • 0x04 Host unreachable
  • 0x05 Connection refused
  • 0x06 TTL expired
  • 0x07 Command not supported
  • 0x08 Address type not supported
  • 0x09 to 0xff unassigned

이후 서버와의 연결은 그대로 TCP Tunnel로서 작동합니다.

부록

CONNECT

TCP Tunnel을 형성합니다.

BIND

클라이언트가 서버의 연결을 수락해야 합니다. FTP 등의 Protocol에서 사용되며, BIND 과정에서 두 개의 응답이 전송되는데 첫 번째 응답은 새로운 소켓을 바인드 했을 때. 그리고 두 번째 응답은 연결이 성공하거나 실패했을때 전송됩니다.

UDP ASSOCIATE

UDP ASSOCIATE의 경우 응답 DST.ADDR과 DST.PORT가 클라이언트가 UDP 송신에 사용할 주소가 됩니다. 이때, TCP 연결은 계속 유지해야 합니다.