SOCKS

**SOCKS**は、インターネット・プロトコル・スイートにおいて、Transmission Control Protocol（TCP）および User Datagram Protocol（UDP）による通信を代理するプロキシのプロトコルである。主にTCPのために設計されている。認証の機能の規定もあるため、それが実装されていれば認証にもとづき、認可された接続のみ接続を許可するような設定もできる。DARPAモデルの観点からは、3番めの層にあるTCP及びUDPによる通信を代理するものであり、使い方にも依るが通常は4番目のアプリケーション層からは透過ではない。例えばウェブブラウザのようなアプリケーションから利用する場合は、ネットワーク接続に関する設定として明示的にプロキシとして指定が必要である。ポート番号には1080がよく使われている。

## 歴史
SOCKSは当初、MIPS Computer Systemsのシステム管理者であるDavid Koblasによって開発された。Koblasは、MIPS Computer Systemsが1992年にSilicon Graphicsによって吸収合併された後に、その年のUsenix Security SymposiumでSOCKSの研究論文を公開した。これによりSOCKSはパブリックに利用できるようになった。SOCKSは、NECのYing-Da Leeによってバージョン4に拡張された。

SOCKS関連のアーキテクチャやクライアントはPermeo Technologiesが所有している。なお、Permeo Technologiesは、NECからスピンオフしたBlue Coat Systemsによって吸収合併された。

SOCKS5プロトコルは、もともとはファイアウォールの一部として、他のセキュリティ製品とともに管理を容易にするために作られたセキュリティプロトコルだった。1996年にIETFによって承認された。SOCKS5は、アジア外の技術を販売している企業Aventail Corporationの協力のもとに開発された。

## 使用例
*SOCKS*は迂回のためのツールとしても使用されることがある。たとえば、政府、職場、学校、特定の国限定のウェブサービスなどで、インターネットのコンテンツへのアクセスフィルタやブロッキングが行われている場合に、それらを回避することができる。

たとえば、Tor onion proxyソフトウェアは、クライアントに対して、SOCKSインターフェイスを提供している。

OpenSSHはSOCKSプロトコルを利用した「動的ポートフォワード」の機能を持っている。SSHサーバ側で許可されていれば、クライアント側からは `ssh(1)` コマンドにある `-D` オプションで利用でき、sshコマンドのプロセスがローカルなSOCKSプロキシのようにして見えるようになる。そのプロキシへの接続はSSHサーバ側へポートフォワードされ、最終的な接続先からはSSHサーバからのアクセスとして見える。。

## サイバー犯罪における使用
クラッキングされたコンピュータには、ボットネットの制御を隠したりクレジットカード詐欺等といった、マルウェア的な目的のために、SOCKS proxyソフトウェアが設定されることがある。

## 解説

SOCKSは、ネットワーク・ファイアウォール越えやアクセス制御等を目的として、クライアントサーバ型のプロトコルが、透過的に使用できるよう設計されたプロキシ（proxy）のプロトコル、及びシステム（の一つ）である。"SOCKetS"  の略。

いわゆるTCP/IPの4層モデル（インターネット・プロトコル・スイートのDARPAモデル）の観点からは、Internet Protocol（IP）の上の、TCPやUDP（ただしUDPに関しては有用性が限られる）のようなトランスポート層における通信の手続きを中継・代理するメカニズムとなっている。SOCKSサーバ自身とクライアント間の通信はストリーム指向であり、一般にはLAN内からTCPで接続する。

プロトコル上は多段にもできるが、原理の説明には1段階で十分なので、以下はそのような前提とする。またファイアウォールを設けないシステムでもユースケースは考えられるが、以下ではファイアウォールの存在を前提とする。

似たような目的のための他のプロキシ類と同様、SOCKSサーバはその目的から、内外のネットワークの両方が見えるファイアウォール自身、あるいはDMZ内に置く。そうでない場合は、SOCKSサーバのみは外部との通信を可能にする、あるいは、内部からSOCKサーバにだけは通信を可能にする、といったような設定が必要となる。

そして、内側から外部に通信する必要があるノードは、代わりにSOCKSサーバに接続し、SOCKSサーバがプロキシとして代わりに外部と通信する。SOCKSプロキシは、例えば、クライアントが外部サーバにアクセスする資格を制御するなどといった、認証や認可を掛けることもできる。SOCKSはまた正反対にも使用することができる。つまり、ファイアウォールの外側の許可された外部クライアントのみが、物理的にはファイアウォールの内側にある、公開のサービスを提供するサーバのみに接続できるようにする、といった用途のための設定もできる。

## プロトコル

### SOCKS 4
標準の SOCKS 4 接続では、以下のような通信が行われる。

SOCKS クライアントからサーバ:

* フィールド 1: SOCKS バージョン番号,1バイト,このバージョンでは 0x04 でなくてはならない
* フィールド 2: コマンドコード,1バイト：
** 0x01 = TCP/IP ストリーム接続を確立する
** 0x02 = TCP/IP ポートバインディングを確立する
* フィールド 3: ネットワークバイトオーダのポート番号,2バイト
* フィールド 4: ネットワークバイトオーダの IP アドレス,4バイト
* フィールド 5: ユーザID文字列, 可変長, null (0x00) で終了させる

SOCKS サーバからクライアント:

* フィールド 1: null バイト
* フィールド 2: 状態,1バイト
** 0x5a = リクエストの許可
** 0x5b = リクエストの拒絶または失敗
** 0x5c = リクエストはクライアントが identd を起動していなかったので失敗(もしくは、サーバから到達できなかった)
** 0x5d = リクエストはクライアントの identd がリクエストにユーザID文字列を確認できなかったので失敗
* フィールド 3: 任意の2バイト,無視されなければならない
* フィールド 4: 任意の4バイト,無視されなければならない

例:

これは、66.102.7.99:80にユーザ「Fred」を接続する SOCKS 4 のリクエストである。そして、サーバは、"OK"の返事をする。

* クライアント: 0x04 | 0x01 | 0x00 0x50 | 0x42 0x66 0x07 0x63 | 0x46 0x72 0x65 0x64 0x00
** 最後のフィールドは ASCII コードの「Fred」であり、次に1バイトの null が続く
* サーバ: 0x00 | 0x5a | 0xXX 0xXX | 0xXX 0xXX 0xXX 0xXX
** 0xXX は全てのバイト値になることができる。 Socks 4 プロトコルはそれらのバイト値が無視されなければならないことを規定している。

この時点以降、 SOCKS クライアントから SOCKS サーバまで送る全てのデータは66.102.7.99に向けて中継される。そして、 SOCKS サーバから SOCKS クライアントに送る場合も同様である。

コマンドフィールドは、 "connect" で 0x01 、あるいは、 "bind" で 0x02 になることができる。 "bind" は動作中の FTP のようなプロトコルのために入ってくる接続を許可する。

### SOCKS 4a

SOCKS 4a は、 SOCKS 4 プロトコルのシンプルな拡張機能であり、宛先ホストのドメイン名を解決できないクライアントがドメイン名を指定することを可能にする。

クライアントは宛先アドレスの最初の3バイトを NULL に、そして最後のバイトを0でない値に設定すべきである(これは、ｘ を非零の値として、 IP アドレス 0.0.0.x に対応する。この値は宛先アドレスとして使用してはならない。したがって、この値は、もしクライアントがドメイン名を解決できるならば、決して設定するべきではない。)。

ユーザ ID を終了する NULL バイトの次に、クライアントは宛先ドメイン名を送らなければならない、そして、それを別の NULL バイトで終了させなければならない。これは "connect" と "bind" の両方のリクエストに使われる。

SOCKS クライアントからサーバ:

* フィールド 1: SOCKS バージョン番号,1バイト,このバージョンでは 0x04 でなくてはならない
* フィールド 2: コマンドコード,1バイト：
** 0x01 = TCP/IP ストリーム接続を確立する
** 0x02 = TCP/IP ポートバインディングを確立する
* フィールド 3: ネットワークバイトオーダのポート番号,2バイト
* フィールド 4: ネットワークバイトオーダの IP アドレス,4バイト
* フィールド 5: ユーザ ID 文字列, 可変長, null (0x00) で終了させる
* フィールド 6: 接続先のホストのドメイン名, 可変長, null (0x00) で終了させる

SOCKS サーバからクライアント:

* フィールド 1: null バイト
* フィールド 2: 状態,1バイト
** 0x5a = リクエストの許可
** 0x5b = リクエストの拒絶または失敗
** 0x5c = リクエストはクライアントが identd を起動していなかったので失敗(もしくは、サーバから到達できなかった)
** 0x5d = リクエストはクライアントの identd がリクエストにユーザ ID 文字列を確認できなかったので失敗
* フィールド 3: ネットワークバイトオーダのポート番号,2バイト
* フィールド 4: ネットワークバイトオーダの IP アドレス,4バイト

4A プロトコルを使用するサーバはリクエストパケット内の宛先アドレスをチェックしなければならない。宛先アドレスが、 x を非零の値としてアドレス 0.0.0.x を表現するならば、サーバはクライアントがパケット内に送付するドメイン名を読み込まなければならない。サーバはドメイン名を解決すべきであり、そしてそれが可能であるならば、宛先ホストへの接続を確立しなくてはならない。

### SOCKS 5

より多くの認証の選択を提供する SOCKS 4 プロトコルの拡張である SOCKS 5 プロトコルは RFC 1928 内で定義されている。最初のハンドシェイクは下記の事項から成り立つ。

* クライアントは接続し、サポートされた認証方法のリストを含む挨拶を送る。
* サーバは一つ選ぶ(もしくは、提供されたメソッドがアクセスできないならば、失敗の応答を送る)。
* いくつかのメッセージが、選択された認証方法に応じて、クライアントとサーバーの間を送受信される。
* クライアントは、接続要求を SOCKS 4 と同じように送る。
* サーバは SOCKS 4 と同じように応答する。

サポートされた認証方法は次の通りに番号を割り付けている：

* 0x00 - 認証なし
* 0x01 - GSSAPI
* 0x02 - ユーザ名/パスワード
* 0x03-0x7F - IANA により割り当てられたメソッド
* 0x80-0xFE - プライベート使用のために予約されたメソッド

クライアントからの最初の挨拶：

* フィールド 1: SOCKS バージョンナンバ(このバージョンでは 0x05 でなくてはならない)
* フィールド 2: サポートされた認証方法の数,1バイト
* フィールド 3: 認証方法, 可変長, サポートされたメソッドにつき1バイト

サーバの選択が伝えられる：

* フィールド 1: SOCKS バージョン, 1バイト(このバージョンでは 0x05 でなくてはならない)
* フィールド 2: 選択された認証方法, 1バイト, もしくはアクセスできないメソッドが提供した 0xFF

次の認証は認証方法によって異なり、 RFC 1929 で記述されている。

クライアントの認証要求：
* フィールド 1: バージョン番号, 1バイト( 0x01 でなくてはならない)
* フィールド 2: ユーザ名長,1バイト
* フィールド 3: ユーザ名
* フィールド 4: パスワード長,1バイト
* フィールド 5: パスワード

認証のためのサーバの応答:

* フィールド 1: バージョン, 1バイト
* フィールド 2: 状態コード,1バイト
** 0x00 = 成功
** 他の全ての値 = 失敗, 接続は終了されなければならない

クライアントの接続要求：

* フィールド 1: SOCKS バージョン番号, 1バイト(このバージョンでは 0x05 でなくてはならない)
* フィールド 2: コマンドコード,1バイト：
** 0x01 = TCP/IP ストリーム接続を確立する
** 0x02 = TCP/IP ポートバインディングを確立する
** 0x03 = UDP ポートを結合させる
* フィールド 3: 予約されている, 0x00 でなければならない
* フィールド 4: アドレスタイプ, 1バイト:
** 0x01 = IPv4アドレス
** 0x03 = ドメイン名
** 0x04 = IPv6アドレス
* フィールド 5: 宛先アドレス
** IPv4 用の4バイト
** 1バイトのドメイン名長に続けて、ドメイン名
** IPv6 用の16バイト
* フィールド 6: ネットワークバイトオーダのポート番号, 2バイト

サーバの応答：

* フィールド 1: SOCKS プロトコルバージョン, 1バイト(このバージョンでは 0x05 でなくてはならない)
* フィールド2: 状態,1バイト
** 0x00 = リクエストの許可
** 0x01 = 一般的な失敗
** 0x02 = ルール設定により許可されない接続
** 0x03 = 到達できないネットワーク
** 0x04 = 到達できないホスト
** 0x05 = 宛先ホストにより拒否された接続
** 0x06 = TTL の期限切れ
** 0x07 = サポートされていないコマンド/ プロトコルエラー
** 0x08 = サポートされないアドレスタイプ
* フィールド 3: 予約されている, 0x00 でなければならない
* フィールド 4: アドレスの種類, 1バイト:
** 0x01 = IPv4 アドレス
** 0x03 = ドメイン名
** 0x04 = IPv6 アドレス
* フィールド 5: サーバ側でbindされたアドレス
** IPv4 用の4バイト
** 1バイトのドメイン名長に続けて、ドメイン名
** IPv6 用の16バイト
* フィールド 6: ネットワークバイトオーダのポート番号, 2バイト

SOCKSによって外部ネットワークに接続する、全てのネットワーク・ソフトウェアの適合を可能にする "socksify"http://mindprod.com/jgloss/socksify.html というクライアント用のプログラムがある。

## ソフトウェア
*Dante は Inferno Nettverk A/S によって開発され、商業的サポートを伴ったオープンソースの SOCKS4/SOCKS5 実装である。
*DeleGate 多機能なProxyソフトウェア。SOCKS4/SOCKS5サーバとしての他、多段プロキシ的に自身の接続のためにSOCKSを使うクライアントとしての機能もある。
*FreeCap Windows 用の Socksifyer , 全てのアプリケーションは、一つの SOCKS あるいは HTTP proxy によって、そのネットワークトラフィックを透過的に実行することができる。
*Kernel SOCKS Bouncer ksb26 (Kernel Socks Bouncer) は socks 4/5 chains を介して、TCP接続(ユーザが定義した目的ホストに向けて)をリダイレクトする Linux Kernel 2.6.x Loadable Kernel Module である。
*OpenSSH は、動的ポートフォワード機能を利用するためのインタフェースのひとつとして、SOCKS プロトコルを使うことができる。OpenSSH クライアントを仮想的な SOCKS サーバの受付側にすることができ、接続先の OpenSSH サーバが仮想的な SOCKS サーバの出口側となって、クライアントからのネット接続を代理する。
*SOcat Multipurpose は (SOcket CAT) を中継する: socks4 とsocks4a の機能性を含む (Linux / Mac)
*SS5 Socks Server はオープンソースの SOCKS4/SOCKS5 サーバである.
*Tor
*WinSocks は Proxy Labs により開発された軽量 SOCKS4/SOCKS5 サーバである。

## 参考文献

## 外部リンク

* draft-ietf-aft-socks-chap Challenge-Handshake Authentication Protocol for SOCKS V5
*  - A SOCKS-based IPv6/IPv4 Gateway Mechanism
*  - GSS-API Authentication Method for SOCKS Version 5 
*  - Username/Password Authentication for SOCKS V5
*  - SOCKS Protocol Version 5
* SOCKS: A protocol for TCP proxy across firewalls - SOCKS Protocol Version 4 (NEC)