SOCKS5 및 SOCKS4 프록시
SOCKS 프록시를 사용하면 애플리케이션이 중계 서버에 대신 대상에 연결하도록 요청할 수 있습니다. 프록시는 요청된 연결을 열고 데이터를 양방향으로 전달합니다. 애플리케이션은 자체 프로토콜을 그대로 사용하므로 웹 요청, API 클라이언트, 파일 전송 등 SOCKS를 지원하는 여러 소프트웨어에서 사용할 수 있습니다.
새 구성을 만들 때는 보통 SOCKS5가 더 유용한 선택지를 제공합니다. 더 다양한 주소 형식, 인증 방식 선택, UDP 지원이 있습니다. SOCKS4는 이전 버전을 요구하는 소프트웨어에 여전히 유용합니다. 이 프로토콜들과 HTTP 프록시 사이의 전반적인 선택은 SOCKS와 HTTP 프록시 비교에서 다룹니다.
애플리케이션이 SOCKS를 통해 연결하는 방법
애플리케이션이 SOCKS5 프록시로 https://example.com/을 여는 경우를 살펴보겠습니다. 먼저 프록시에 접속하고, 웹사이트로 연결을 열도록 요청한 뒤에야 웹사이트 데이터를 주고받습니다. 과정은 네 단계로 나뉩니다.
- 애플리케이션이 TCP로 프록시의 호스트 이름 또는 IP와 수신 포트에 접속합니다.
- 애플리케이션과 프록시가 접근 방식을 선택합니다. 그 방식에 인증 정보가 필요하면 애플리케이션이 이를 보내고 프록시가 확인합니다.
- 애플리케이션이 대상 주소와 포트를 담은
SOCKS CONNECT요청을 보냅니다. 프록시는 접근 규칙을 확인하고 대상 연결을 시도한 뒤 결과를 알립니다. - 성공 응답 후 애플리케이션은 프록시를 통해 대상과 통신합니다. HTTPS 웹사이트라면 웹 요청을 보내기 전에 사이트와 TLS 연결을 수립하고 인증서를 검증합니다.
두 포트 번호는 서로 다른 서버에 속합니다. 예를 들어 프록시는 proxy.example:1080에서 수신하고 웹사이트는 example.com:443으로 접속할 수 있습니다. SOCKS에는 관례적으로 포트 1080을 사용하지만 서비스가 다른 포트를 사용할 수도 있습니다. 프록시에 지정된 수신 포트를 사용하세요. 이 포트가 대상 포트를 대신하지는 않습니다.
일반적인 TCP 전달에서 SOCKS는 각 HTTP 요청이나 파일 명령을 해석하지 않고 애플리케이션의 바이트 스트림을 전달합니다. 애플리케이션은 계속 자체 프로토콜로 대상과 통신합니다. 그래서 같은 SOCKS 연결 방식으로 웹 클라이언트와 다른 종류의 소프트웨어를 지원할 수 있습니다.
CONNECT는 SOCKS 안에서 자체 메시지 형식을 사용하는 명령이며, HTTP CONNECT 메서드와 다릅니다. SOCKS는 활성 FTP처럼 서버가 프록시를 통해 역방향으로 접속해야 하는 애플리케이션을 위해 BIND도 정의합니다. BIND는 별도 지원이 필요하며 일반적인 웹사이트 또는 API 요청에는 사용하지 않습니다.
SOCKS4, SOCKS4a, SOCKS5의 차이
SOCKS4는 IPv4 주소로 TCP 연결을 엽니다. SOCKS4a에는 호스트 이름을 보내는 옵션이 추가돼 프록시가 DNS로 IP를 찾을 수 있습니다. SOCKS5는 인증 방식을 선택할 수 있고 IPv4 주소, IPv6 주소, 호스트 이름을 받으며 UDP 전달을 정의합니다.
| 기능 | SOCKS4 | SOCKS4a | SOCKS5 |
|---|---|---|---|
| 외부로 나가는 TCP 연결 | 지원 | 지원 | 지원 |
| 요청에 담는 대상 | IPv4 주소 | IPv4 주소 또는 도메인 이름 | IPv4 주소, IPv6 주소 또는 도메인 이름 |
| 프록시의 호스트 이름 조회 | 미지원 | 지원 | 지원 |
| 표준 사용자 이름/비밀번호 방식 | 미지원 | 미지원 | 지원 |
| UDP 중계 방식 | 미지원 | 미지원 | 지원 |
이는 프로토콜의 기능입니다. 사용하려는 특정 기능을 클라이언트와 프록시 서비스가 구현해야 합니다. 예를 들어 SOCKS5 서비스가 TCP 연결은 처리하지만 사용할 수 있는 UDP 중계는 제공하지 않을 수 있습니다.
SOCKS5 요청에는 IPv6 대상을 담을 수 있지만 프록시 역시 해당 IPv6 서버에 도달할 수 있어야 합니다. 두 연결은 서로 다른 IP 버전을 사용할 수 있습니다. 애플리케이션은 IPv4로 프록시에 접속하고, 프록시는 IPv6로 대상에 연결할 수 있습니다.
SOCKS4a는 SOCKS4의 확장이지 모든 SOCKS4 연결의 다른 이름이 아닙니다. 오래된 클라이언트가 IPv4 주소만 보낸다면 SOCKS4를 선택해도 원격 DNS가 생기지 않습니다. SOCKS4a는 양쪽의 지원이 필요합니다. 둘 다 지원한다면 보통 SOCKS5가 더 간단한 선택입니다. SOCKS4를 선택하는 것만으로 출구 IP의 평판이나 속도가 나아지지는 않습니다.
대상 이름은 누가 확인하는가
이름이 있는 서버에 연결하려면 먼저 이름을 IP 주소로 변환해야 합니다. SOCKS5는 해당 조회 결과와 이름 자체를 모두 받을 수 있습니다. 어느 쪽을 보낼지는 클라이언트의 DNS 설정이 결정합니다.
로컬 DNS에서는 애플리케이션이 설정된 DNS 해석기에 reports.example을 질의합니다. 응답이 203.0.113.27이라고 가정하면 애플리케이션은 203.0.113.27:443으로 SOCKS 연결을 요청합니다. 이후 웹사이트 연결은 프록시를 거치지만 조회는 이미 클라이언트 측에서 이루어졌습니다.
프록시 측 DNS에서는 애플리케이션이 대상을 먼저 로컬에서 조회하지 않고 reports.example:443을 보냅니다. 프록시가 DNS로 IP를 얻고 요청된 연결을 엽니다. 호스트 이름은 SOCKS 요청의 일부로 프록시에 전달됩니다.
클라이언트는 확인할 수 없지만 프록시는 확인할 수 있는 이름을 사용할 때 도움이 될 수 있습니다. 일부 서비스는 DNS 해석기에 따라 다른 주소를 반환하므로 조회 위치를 옮기면 연결을 받는 서버가 달라질 수 있습니다. 프록시의 출구 국가를 설정하거나 사이트의 요청 수락을 보장하는 기능은 아닙니다.
curl에서는 다음 두 명령으로 두 DNS 모드를 선택합니다.
curl --proxy socks5://proxy.example:1080 https://example.com/
curl --proxy socks5h://proxy.example:1080 https://example.com/
socks5://는 curl이 웹사이트 이름을 로컬에서 확인하게 하고, socks5h://는 이름을 프록시에 전달합니다. 둘 다 SOCKS5를 사용합니다. h는 이 클라이언트의 URL 문법에서 프록시가 호스트 이름을 확인한다는 뜻입니다. SOCKS5를 HTTPS로 바꾸거나 암호화를 추가하지 않습니다. 다른 애플리케이션은 체크박스를 사용하거나 원격 DNS를 자동으로 선택할 수 있습니다. 예시 프록시 호스트 이름과 포트를 실제 서비스 정보로 바꾸고 필요한 인증 정보를 입력하세요.
SOCKS5 TCP 요청에 도메인 이름을 넣어 보내는 데 UDP 중계 지원은 필요하지 않습니다. 프록시는 자체 DNS 설정으로 조회합니다. 클라이언트의 UDP 패킷을 SOCKS5로 전달하도록 요청하는 것과는 다릅니다.
대상 DNS를 프록시에 맡기도록 설정한 클라이언트가 로컬에서 조회하면 요청한 이름이 의도한 경로 밖에 노출됩니다. 이를 DNS 누출이라고 합니다. 암호화된 DNS는 DNS 해석기와의 교환을 보호하지만 해석기는 여전히 이름을 받습니다. 프록시 자체의 호스트 이름을 조회하는 작업은 별개이며, 다른 애플리케이션은 각자 DNS 동작을 유지합니다. 한 프로그램의 원격 DNS가 기기의 모든 조회를 옮기는 것은 아닙니다.
인증과 암호화
SOCKS5에서는 클라이언트가 지원하는 인증 방식을 제시하고 프록시가 하나를 선택합니다. 사용자 이름과 비밀번호가 한 가지 옵션입니다. SOCKS 로그인 교환 없이 연결하는 방식도 있습니다. 서비스는 클라이언트의 출발지 IP를 허용 목록과 대조한 뒤 이를 허용할 수 있습니다. 따라서 비밀번호 필드가 없는 엔드포인트도 접근을 제한할 수 있습니다.
인증 방식에 합의하지 못한 것은 비밀번호가 거부된 것과 다릅니다. 전자의 경우 비밀번호 교환이 아직 이루어지지 않았습니다. 사용자 이름/비밀번호를 지원하지 않는 클라이언트는 SOCKS5 설정이 있다는 이유만으로 비밀번호 전용 SOCKS5 엔드포인트를 사용할 수 없습니다. SOCKS4에는 사용자 ID 필드가 있지만 동일한 표준 비밀번호 교환은 없습니다. 그래도 서버는 접근 규칙을 적용할 수 있습니다.
일반적인 SOCKS5 사용자 이름/비밀번호 교환은 인증 정보를 암호화하지 않습니다. 애플리케이션이 대상과 HTTPS 연결을 수립하기 전에 이루어지므로 이후의 HTTPS 연결이 앞선 프록시 로그인을 보호하지 않습니다. 클라이언트에서 프록시까지의 경로를 암호화하려면 별도 보호 연결이나 명시적으로 지원되는 보안 방식이 필요합니다.
일반적인 SOCKS 전달에서는 인증서 검증을 활성화하고 TLS 가로채기를 사용하지 않을 때 HTTPS가 애플리케이션과 웹사이트의 교환을 보호합니다. 암호화되지 않은 애플리케이션 프로토콜은 중계를 거쳐도 암호화되지 않은 상태입니다. SOCKS5 지원이나 비밀번호 인증만으로 트래픽 암호화가 보장되지는 않습니다.
프록시는 여전히 접속한 클라이언트 IP, 요청 대상, 연결 시점을 압니다. 대상은 프록시의 출구 IP를 보고 자신을 향한 애플리케이션 데이터를 받습니다. 쿠키, 계정 로그인 등 애플리케이션 식별자로도 사용자를 알아볼 수 있습니다. SOCKS 버전을 바꿔도 이러한 정보는 사라지지 않습니다.
SOCKS5가 TCP와 UDP를 전달하는 방식
TCP는 순서가 있는 바이트 스트림을 제공합니다. 클라이언트가 해당 경로를 지원하고 프록시가 대상을 허용하면 브라우저 요청, API 호출, SSH 세션에서 SOCKS TCP 연결을 사용할 수 있습니다. 웹사이트의 포트 443에 접속했다고 다른 애플리케이션의 포트도 사용할 수 있다는 뜻은 아닙니다.
UDP는 별도의 데이터그램을 보냅니다. SOCKS5 클라이언트는 먼저 TCP 제어 연결을 열고 UDP ASSOCIATE로 중계를 요청합니다. 프록시는 중계 주소와 UDP 포트를 반환합니다. 클라이언트는 대상을 설명하는 SOCKS 헤더를 붙인 데이터그램을 그곳으로 보냅니다. TCP 제어 연결을 닫으면 이 UDP 연결 관계도 끝납니다. 데이터그램은 일반 SOCKS CONNECT 스트림 안이 아니라 제어 연결과 별도로 이동합니다.
애플리케이션과 서비스 모두 이 방식을 지원해야 하고 네트워크에서 UDP 경로를 허용해야 합니다. TCP 로그인은 완료돼도 음성, 게임 또는 다른 UDP 기능은 실패할 수 있습니다. SOCKS CONNECT를 통한 HTTPS 요청 성공은 TCP 전달을 보여 줄 뿐, UDP 작동을 입증하지 않습니다. QUIC은 UDP를 사용하지만 실제 사용 가능 여부는 클라이언트와 전체 경로에도 달려 있습니다. SOCKS5라는 표시만으로 이를 확인할 수는 없습니다.
SOCKS가 유용한 경우
SOCKS는 소프트웨어가 자체 애플리케이션 프로토콜을 유지하면서 중계 연결이 필요할 때 유용합니다. 스크립트는 할당된 출구 IP로 API 데이터를 요청할 수 있고, 파일 전송 클라이언트는 승인된 경로로 원격 서버에 접속할 수 있으며, 호환되는 데스크톱 애플리케이션은 웹브라우저가 아니어도 프록시를 사용할 수 있습니다. 각각 클라이언트의 SOCKS 지원과 서비스가 허용하는 대상 포트에 따라 달라집니다.
같은 계정이나 서버에서 반복 작업한다면 고정 출구가 적합할 수 있습니다. 독립적인 작업에는 순환 서비스가 유용할 수 있습니다. SOCKS4와 SOCKS5가 이 동작을 결정하지는 않습니다. 출구 IP, 네트워크 유형, 다른 고객의 사용 여부, 변경 시점은 서비스가 결정합니다. 프로토콜 버전이 속도 순위를 제공하는 것도 아닙니다. 경로 길이, 서버 부하, 가용 대역폭이 결과에 영향을 줍니다.
클라이언트 지원 범위는 프로토콜보다 좁을 수 있습니다. Chrome의 내장 SOCKS5 구현은 프록시를 통해 대상 이름을 확인하지만 SOCKS5 사용자 이름/비밀번호 인증이나 UDP 중계를 수행하지 않습니다. 따라서 비밀번호 전용 엔드포인트가 curl에서는 작동해도 브라우저 내장 설정에서는 실패할 수 있습니다. 외부 어댑터는 자체 기능을 가진 별도의 연결 구성요소입니다.
한 프로그램 안에 설정한 프록시는 그 프로그램이 지원하는 연결에 적용됩니다. 별도 다운로더나 스크립트를 설정하지는 않습니다. 시스템 프록시 설정도 이를 사용하는 소프트웨어에만 영향을 줍니다. 자체 SOCKS 지원이 없는 애플리케이션의 연결을 어댑터로 우회할 때는 TCP, UDP, DNS 적용 범위가 중요합니다. SOCKS는 일반 ICMP 전달을 제공하지 않으므로 ping은 이 프록시 경로의 테스트가 아닙니다.
연결 설정과 유용한 테스트
해당 엔드포인트용으로 제공된 프록시 주소, 수신 포트, SOCKS 버전, 접근 방식부터 확인하세요. 1080 같은 숫자만으로 프로토콜을 식별할 수는 없습니다. 같은 주소를 HTTP 전용 프록시 필드에 넣는 대신 클라이언트에서 SOCKS를 선택하세요.
프록시 인증 정보는 중계자 사용 권한을, 웹사이트 로그인은 웹사이트 사용 권한을 부여합니다. 서로 다른 설정에 넣어야 합니다. curl에서 --proxy-user는 프록시 인증 정보를, --user는 대상 인증 정보를 전달합니다. IP 기반 접근에서는 허용 목록이 프록시가 보는 클라이언트 출발지 IP와 일치해야 합니다. 이 IP는 클라이언트가 네트워크를 바꾸면 달라질 수 있습니다.
의도한 DNS 모드를 선택한 뒤 우회 규칙을 확인하세요. 제외 목록에 있는 대상에는 설정한 프록시가 적용되지 않을 수 있습니다. curl에서는 NO_PROXY 때문에 그럴 수 있습니다. 프록시 경로를 명시적으로 테스트하려면 --noproxy ""로 해당 실행 한 번의 제외 설정을 비울 수 있습니다.
실제 작업에 사용할 프로그램에서 테스트하세요. IP 확인용 엔드포인트나 본인이 관리하는 대상 서버 로그로 요청의 출발지 IP를 볼 수 있습니다. 직접 요청한 결과와 비교하세요. 프록시에 접속할 때 사용하는 주소와 대상에서 보는 출구 주소는 같지 않을 수 있습니다.
그다음 실제 작업을 시도하세요. IP 변경은 테스트한 요청의 경로를 보여 주지만 모든 전송 방식을 측정하거나 다른 사이트의 응답을 확인해 주지는 않습니다. 작업에 UDP나 IPv6가 필요하면 별도로 테스트하고, 실제 작업을 대표하는 부하에서 응답 시간과 연결 안정성을 평가하세요.
연결 단계별 오류 확인
프록시 접속, 접근 권한 획득, 대상 연결 열기, 애플리케이션 응답 수신을 구분하세요. 단계마다 실패 원인이 다릅니다.
| 실패 내용 | 확인할 사항 |
|---|---|
| 프록시 연결 시간 초과 또는 거부 | 프록시 호스트 이름, 수신 포트, 네트워크 도달 가능 여부, 접근 제한. 아직 대상 연결은 열리지 않은 상태입니다. |
| 사용 가능한 인증 방식 없음 | 클라이언트가 해당 엔드포인트에서 허용하는 방식을 지원하는지 확인하세요. 아직 비밀번호에 대한 판정은 아닙니다. |
| 사용자 이름/비밀번호 로그인 거부 | 비밀번호 방식이 선택됐는지 확인한 뒤 프록시 인증 정보와 계정 접근 권한을 확인하세요. |
| 대상 이름을 확인할 수 없음 | 어느 쪽에서 조회하는지 확인하세요. 로컬 DNS 오류는 클라이언트가 SOCKS에 대상 연결을 열도록 요청하기 전에 발생할 수 있습니다. 원격 DNS에서는 프록시가 대상 IP를 얻어야 합니다. |
| 프록시가 대상 또는 동작을 거부 | 접근 규칙, 대상 포트, 요청한 명령이나 주소 유형의 지원 여부를 확인하세요. 정책상 거부는 UDP 명령이나 IPv6 주소의 미지원과 다릅니다. |
| 프록시가 대상에 도달하지 못함 | 프록시 네트워크에서의 대상 주소, 포트, 가용 여부를 확인하세요. 대상에 도달할 수 없거나 대상이 연결을 거부할 수 있습니다. |
검증된 HTTPS 연결이 성공하고 사이트가 로그인 페이지, CAPTCHA 또는 접근 거부를 반환했다면 SOCKS 연결은 이미 그 교환을 전달한 것입니다. 사이트의 응답과 애플리케이션 동작을 조사하세요. 반대로 요청에 평소 공인 IP가 표시된다면 해당 프로그램에서 선택한 프록시와 우회 규칙을 확인하세요.
