<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Tiger Blog]]></title>
  <link href="http://cctiger36.github.io/atom.xml" rel="self"/>
  <link href="http://cctiger36.github.io/"/>
  <updated>2016-06-30T10:30:12+09:00</updated>
  <id>http://cctiger36.github.io/</id>
  <author>
    <name><![CDATA[cctiger36]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[自作 Socks Tunnel の暗号化について]]></title>
    <link href="http://cctiger36.github.io/blog/2016/06/29/encryption-and-decryption-for-socks-tunnel/"/>
    <updated>2016-06-29T17:42:52+09:00</updated>
    <id>http://cctiger36.github.io/blog/2016/06/29/encryption-and-decryption-for-socks-tunnel</id>
    <content type="html"><![CDATA[<p>前回の <a href="http://cctiger36.github.io/blog/2015/12/23/self-made-socks-tunnel/">Firewall を貫くツールを自作してみた</a> の続きです。今回は暗号化の部分を補完します。</p>

<p>基本的は SSL/TLS のデータ送受信の段階と同じ<a href="https://www.wikiwand.com/ja/%E5%85%B1%E9%80%9A%E9%8D%B5%E6%9A%97%E5%8F%B7">共通鍵暗号</a>を使えばいいです。<br/>
今回はとりあえず一番普通の AES-256-CBC で暗号化しようと思ういます。(アルゴリズムは簡単に変えられます)</p>

<p>Ruby でやるなら <a href="http://ruby-doc.org/stdlib-2.3.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html">OpenSSL::Cipher</a> を使えば簡単に実装できます。</p>

<p>暗号化と復号化用のクラスはこんな感じです。基本的は Ruby のドキュメント通りです。</p>

<figure class='code'><figcaption><span>coder.rb</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s2">&quot;openssl&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="no">CIPHER</span> <span class="o">=</span> <span class="s2">&quot;AES-256-CBC&quot;</span>
</span><span class='line'><span class="no">SALT</span> <span class="o">=</span> <span class="s2">&quot;V</span><span class="se">\x11\x97\xA6</span><span class="s2">r</span><span class="se">\xEF</span><span class="s2">[</span><span class="se">\xFE</span><span class="s2">&quot;</span>
</span><span class='line'><span class="no">PASSWORD</span> <span class="o">=</span> <span class="s2">&quot;mypassword&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Coder</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">initialize</span>
</span><span class='line'>    <span class="n">cipher</span> <span class="o">=</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="no">CIPHER</span><span class="p">)</span>
</span><span class='line'>    <span class="n">key_iv</span> <span class="o">=</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">PKCS5</span><span class="o">.</span><span class="n">pbkdf2_hmac_sha1</span><span class="p">(</span><span class="no">PASSWORD</span><span class="p">,</span> <span class="no">SALT</span><span class="p">,</span> <span class="mi">2000</span><span class="p">,</span> <span class="n">cipher</span><span class="o">.</span><span class="n">key_len</span> <span class="o">+</span> <span class="n">cipher</span><span class="o">.</span><span class="n">iv_len</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@key</span> <span class="o">=</span> <span class="n">key_iv</span><span class="o">[</span><span class="mi">0</span><span class="p">,</span> <span class="n">cipher</span><span class="o">.</span><span class="n">key_len</span><span class="o">]</span>
</span><span class='line'>    <span class="vi">@iv</span> <span class="o">=</span> <span class="n">key_iv</span><span class="o">[</span><span class="n">cipher</span><span class="o">.</span><span class="n">key_len</span><span class="p">,</span> <span class="n">cipher</span><span class="o">.</span><span class="n">iv_len</span><span class="o">]</span>
</span><span class='line'>
</span><span class='line'>    <span class="vi">@encoder</span> <span class="o">=</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="no">CIPHER</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@encoder</span><span class="o">.</span><span class="n">encrypt</span>
</span><span class='line'>    <span class="vi">@encoder</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="vi">@key</span>
</span><span class='line'>
</span><span class='line'>    <span class="vi">@decoder</span> <span class="o">=</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="no">CIPHER</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@decoder</span><span class="o">.</span><span class="n">decrypt</span>
</span><span class='line'>    <span class="vi">@decoder</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="vi">@key</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">encode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@encoder</span><span class="o">.</span><span class="n">iv</span> <span class="o">=</span> <span class="vi">@iv</span>
</span><span class='line'>    <span class="vi">@encoder</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="o">+</span> <span class="vi">@encoder</span><span class="o">.</span><span class="n">final</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">decode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@decoder</span><span class="o">.</span><span class="n">iv</span> <span class="o">=</span> <span class="vi">@iv</span>
</span><span class='line'>    <span class="vi">@decoder</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="o">+</span> <span class="vi">@decoder</span><span class="o">.</span><span class="n">final</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>キーと IV を手元で作っても構わないが、ドキュメント通りに <a href="https://www.wikiwand.com/en/PBKDF2">PBKDF2</a> を使って、パスワードとソルトから生成したほうが正しい道と思います。<br/>
もちろんパスワードとソルトをソースコードに書くのも良くないですけど、ここは一旦置いといて、とりあえず暗号化と復号化ができればいいです。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>irb
</span><span class='line'>2.3.0 :001 &gt; require_relative <span class="s2">&quot;coder&quot;</span>
</span><span class='line'>2.3.0 :002 &gt; <span class="nv">coder</span> <span class="o">=</span> Coder.new
</span><span class='line'> <span class="o">=</span>&gt; <span class="c">#&lt;Coder:0x007ffa4a04b1d0 @key=&quot;\xE4\xC6\xDF\x80\xE7\x81k\x7F\b@\ezo\x18@~U}\xE9\xA9\xE4++\xAE\x92X\x81\xE8\tu\xD6(&quot;, @iv=&quot;S\x8C\xC6\xB8\x97l\xACu\xD4O\xB7\xEF\xAA\x11\xCB\xD3&quot;, @encoder=#&lt;OpenSSL::Cipher:0x007ffa4a04b108&gt;, @decoder=#&lt;OpenSSL::Cipher:0x007ffa4a04b0e0&gt;&gt;</span>
</span><span class='line'>2.3.0 :003 &gt; <span class="nv">encoded</span> <span class="o">=</span> coder.encode<span class="o">(</span><span class="s2">&quot;test12345&quot;</span><span class="o">)</span>
</span><span class='line'> <span class="o">=</span>&gt; <span class="s2">&quot;,\x81\xFD\xEE\v\x91fr\xA1eC\xECR:\x00\xF0&quot;</span>
</span><span class='line'>2.3.0 :004 &gt; coder.decode<span class="o">(</span>encoded<span class="o">)</span>
</span><span class='line'> <span class="o">=</span>&gt; <span class="s2">&quot;test12345&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>後は前回残した TODO のところにこの <code>Coder</code> を適用すればいいです。</p>

<p>ここでちょっとハマったところは、EventMachine::Connection#send_data はメッセージをまるごと送信するとは限らないです。途切れ途切れになるかもしれません。<br/>
暗号化しない場合は特に問題ないだけど、暗号化すると、どこからどこまでは１つのメッセージなのかがわからないと、ちゃんと複合できなくなります。<br/>
だから人為的に区切りのものをメッセージの間に入れることになりました。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">send_encoded_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>  <span class="k">return</span> <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">nil?</span> <span class="o">||</span> <span class="n">data</span><span class="o">.</span><span class="n">empty?</span>
</span><span class='line'>  <span class="n">send_data</span><span class="p">(</span><span class="vi">@coder</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
</span><span class='line'>  <span class="n">send_data</span><span class="p">(</span><span class="s2">&quot;DRECOMADVENTCALENDAR&quot;</span><span class="p">)</span>  <span class="c1"># 文字列にするかバイナリにするかはお好きにどうぞ</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>通信内容はこんな感じになります。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="ss">HOST</span><span class="p">:</span><span class="no">PORT</span> <span class="p">(</span><span class="no">Encoded</span><span class="p">)</span>
</span><span class='line'><span class="no">DRECOMADVENTCALENDAR</span> <span class="o">&lt;-</span> <span class="no">Delimiter</span>
</span><span class='line'><span class="no">DATA</span> <span class="p">(</span><span class="no">Encoded</span><span class="p">)</span>
</span><span class='line'><span class="no">DRECOMADVENTCALENDAR</span> <span class="o">&lt;-</span> <span class="no">Delimiter</span>
</span><span class='line'><span class="no">DATA</span> <span class="p">(</span><span class="no">Encoded</span><span class="p">)</span>
</span><span class='line'><span class="no">DRECOMADVENTCALENDAR</span> <span class="o">&lt;-</span> <span class="no">Delimiter</span>
</span></code></pre></td></tr></table></div></figure>


<p>複合するところも一旦バッファに入れて、区切りのところまで切り取って順番に復号します。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">receive_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>  <span class="k">return</span> <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">nil?</span> <span class="o">||</span> <span class="n">data</span><span class="o">.</span><span class="n">empty?</span>
</span><span class='line'>  <span class="vi">@buffer</span> <span class="o">&lt;&lt;</span> <span class="n">data</span>
</span><span class='line'>  <span class="kp">loop</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">fore</span><span class="p">,</span> <span class="n">rest</span> <span class="o">=</span> <span class="vi">@buffer</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;DRECOMADVENTCALENDAR&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</span><span class='line'>    <span class="k">break</span> <span class="k">unless</span> <span class="n">rest</span>
</span><span class='line'>    <span class="n">server</span><span class="o">.</span><span class="n">send_data</span><span class="p">(</span><span class="vi">@coder</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="n">fore</span><span class="p">))</span>
</span><span class='line'>    <span class="vi">@buffer</span> <span class="o">=</span> <span class="n">rest</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>これで通信が暗号化され、安心で使えるようになりました。＼(＾▽＾)／<br/>
作りはまだ雑だけど、もう実用できると思います。</p>

<p>具体的なコードはまた <a href="https://github.com/cctiger36/socks-tunnel-demo">Github</a> のほうへどうぞ。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Firewall を貫くツールを自作してみた]]></title>
    <link href="http://cctiger36.github.io/blog/2015/12/23/self-made-socks-tunnel/"/>
    <updated>2015-12-23T12:42:51+09:00</updated>
    <id>http://cctiger36.github.io/blog/2015/12/23/self-made-socks-tunnel</id>
    <content type="html"><![CDATA[<p>これは <a href="http://www.adventar.org/calendars/1044">【その2】ドリコム Advent Calendar 2015</a> 24日目の記事です。<br/>
23日目の記事は hayato240 さんの<a href="http://qiita.com/hayato240/items/d20e27da7d24a3bd3af2">二郎を思い浮かべながら、RSpecを学んだことの振り返り</a> です。<br/>
<a href="http://www.adventar.org/calendars/1043">【その1】ドリコム Advent Calendar 2015</a> もあわせてどうぞ。</p>

<h2>自己紹介</h2>

<p>こんにちは、タイガーです。</p>

<p>中国上海からきてます。ドリコム歴はもう４年目です。<br/>
本業はサーバーサイドのエンジニアです。今年は iOS と Android のクライアントの開発も結構やりました。</p>

<h2>まえがき</h2>

<p>この間 <a href="http://www.wikiwand.com/ja/%E9%87%91%E7%9B%BE">Great Firewall</a> が VPN も遮断するニュースがありまして、ちょっと周りの人とその話をしました。</p>

<p>多分エンジニアの皆さんはご存知と思います。中国にいるならこれを越えないといろいろ不便になります。そのためにいろんなツールも作られています。一番有名のは <a href="https://github.com/shadowsocks/shadowsocks">shadowsocks</a>、見ての通りいつかその存在が消えるかもしれませんね。エンジニアとしてはやはり自分がその仕組を理解すれば一番いいと思います。</p>

<h2>本題</h2>

<p>Firewall を通過するには、<a href="https://www.wikiwand.com/en/SOCKS">SOCKS5</a> っていうプロトコルが存在します。具体的な仕様は <a href="https://www.ietf.org/rfc/rfc1928.txt">RFC1928</a> に定義されています。８ページしかないので、割りとすぐ読み終えます。基本的は SOCKS5 をベースにして作ればいろいろ汎用出来ます。</p>

<p>すでに shadowsocks 大先輩があるので、それを参考にしながら作ってみましょう。言語はもちろん Ruby です。</p>

<!-- more -->


<p>大体な構造は下図の通り</p>

<p><img src="http://cctiger36.github.io/images/socks-tunnel.png"></p>

<ul>
<li>まずはローカルサーバーとリモートサーバー２つの部分があります。</li>
<li>ブラウザとかの SOCKS5 をサポートしてるアプリケーションはローカルサーバーに接続します。</li>
<li>リモートサーバーは Firewall の外にあるサーバーで実行します。</li>
<li>Firewall の外にアクセスする時は <strong>ブラウザ → ローカルサーバー → リモートサーバー → 目標サーバー</strong> の流れになります。</li>
</ul>


<h3>ローカルサーバー</h3>

<p>まず必要なのは並列処理です。ブラウザは同時にたくさんのアクセスがくるので、並列処理ができないと使い物にならないです。今の時代はもちろん Event Driven I/O でやります。Ruby なら <a href="https://github.com/eventmachine/eventmachine">EventMachine</a> があります。</p>

<p>とりあえず EventMachine で実装してみました。ちょっと長いです。(´・ω・｀)</p>

<figure class='code'><figcaption><span>local.rb</span><a href='https://github.com/cctiger36/socks-tunnel-demo/blob/master/local.rb'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
<span class='line-number'>130</span>
<span class='line-number'>131</span>
<span class='line-number'>132</span>
<span class='line-number'>133</span>
<span class='line-number'>134</span>
<span class='line-number'>135</span>
<span class='line-number'>136</span>
<span class='line-number'>137</span>
<span class='line-number'>138</span>
<span class='line-number'>139</span>
<span class='line-number'>140</span>
<span class='line-number'>141</span>
<span class='line-number'>142</span>
<span class='line-number'>143</span>
<span class='line-number'>144</span>
<span class='line-number'>145</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s2">&quot;eventmachine&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="no">LOCAL_SERVER_HOST</span> <span class="o">=</span> <span class="s2">&quot;127.0.0.1&quot;</span>
</span><span class='line'><span class="no">LOCAL_SERVER_PORT</span> <span class="o">=</span> <span class="s2">&quot;8081&quot;</span>
</span><span class='line'><span class="no">REMOTE_SERVER_HOST</span> <span class="o">=</span> <span class="s2">&quot;127.0.0.1&quot;</span>
</span><span class='line'><span class="no">REMOTE_SERVER_PORT</span> <span class="o">=</span> <span class="s2">&quot;8082&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">LocalConnection</span> <span class="o">&lt;</span> <span class="no">EventMachine</span><span class="o">::</span><span class="no">Connection</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:server</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">send_encoded_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="k">return</span> <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">nil?</span> <span class="o">||</span> <span class="n">data</span><span class="o">.</span><span class="n">length</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>    <span class="n">send_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">receive_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="n">server</span><span class="o">.</span><span class="n">send_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">unbind</span>
</span><span class='line'>    <span class="n">server</span><span class="o">.</span><span class="n">close_connection_after_writing</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">module</span> <span class="nn">LocalServer</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">post_init</span>
</span><span class='line'>    <span class="vi">@fiber</span> <span class="o">=</span> <span class="no">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="k">do</span>
</span><span class='line'>      <span class="n">greeting</span>
</span><span class='line'>      <span class="kp">loop</span> <span class="p">{</span> <span class="n">do_command</span> <span class="p">}</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">receive_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="k">if</span> <span class="vi">@connection</span>
</span><span class='line'>      <span class="vi">@connection</span><span class="o">.</span><span class="n">send_encoded_data</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">to_s</span><span class="p">)</span>
</span><span class='line'>    <span class="k">else</span>
</span><span class='line'>      <span class="vi">@data</span> <span class="o">=</span> <span class="n">data</span>
</span><span class='line'>      <span class="vi">@fiber</span> <span class="o">=</span> <span class="kp">nil</span> <span class="k">if</span> <span class="vi">@fiber</span><span class="o">.</span><span class="n">resume</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">unbind</span>
</span><span class='line'>    <span class="vi">@connection</span><span class="o">.</span><span class="n">close_connection</span> <span class="k">if</span> <span class="vi">@connection</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="kp">private</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># IN</span>
</span><span class='line'>    <span class="c1"># +----+----------+----------+</span>
</span><span class='line'>    <span class="c1"># |VER | NMETHODS | METHODS  |</span>
</span><span class='line'>    <span class="c1"># +----+----------+----------+</span>
</span><span class='line'>    <span class="c1"># | 1  |    1     | 1 to 255 |</span>
</span><span class='line'>    <span class="c1"># +----+----------+----------+</span>
</span><span class='line'>    <span class="c1">#</span>
</span><span class='line'>    <span class="c1"># OUT</span>
</span><span class='line'>    <span class="c1"># +----+--------+</span>
</span><span class='line'>    <span class="c1"># |VER | METHOD |</span>
</span><span class='line'>    <span class="c1"># +----+--------+</span>
</span><span class='line'>    <span class="c1"># | 1  |   1    |</span>
</span><span class='line'>    <span class="c1"># +----+--------+</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">greeting</span>
</span><span class='line'>      <span class="n">ver</span> <span class="o">=</span> <span class="vi">@data</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s2">&quot;C&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">first</span>
</span><span class='line'>      <span class="n">clear_data</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">ver</span> <span class="o">==</span> <span class="mi">5</span>
</span><span class='line'>        <span class="n">send_data</span> <span class="s2">&quot;</span><span class="se">\x05\x00</span><span class="s2">&quot;</span>  <span class="c1"># NO AUTHENTICATION REQUIRED</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="n">send_data</span> <span class="s2">&quot;</span><span class="se">\x05\xFF</span><span class="s2">&quot;</span>  <span class="c1"># NO ACCEPTABLE METHODS</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>      <span class="no">Fiber</span><span class="o">.</span><span class="n">yield</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># IN</span>
</span><span class='line'>    <span class="c1"># +----+-----+-------+------+----------+----------+</span>
</span><span class='line'>    <span class="c1"># |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |</span>
</span><span class='line'>    <span class="c1"># +----+-----+-------+------+----------+----------+</span>
</span><span class='line'>    <span class="c1"># | 1  |  1  | X&#39;00&#39; |  1   | Variable |    2     |</span>
</span><span class='line'>    <span class="c1"># +----+-----+-------+------+----------+----------+</span>
</span><span class='line'>    <span class="c1">#</span>
</span><span class='line'>    <span class="c1"># OUT</span>
</span><span class='line'>    <span class="c1"># see the defination of reply_data</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">do_command</span>
</span><span class='line'>      <span class="n">_</span><span class="p">,</span> <span class="n">cmd</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">atype</span><span class="p">,</span> <span class="n">addr_length</span> <span class="o">=</span> <span class="vi">@data</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s2">&quot;C5&quot;</span><span class="p">)</span>
</span><span class='line'>      <span class="n">header_length</span> <span class="o">=</span> <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">case</span> <span class="n">atype</span>
</span><span class='line'>      <span class="k">when</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span>  <span class="c1"># 1: ipv4, 4 bytes / 4: ipv6, 16 bytes</span>
</span><span class='line'>        <span class="n">ip_length</span> <span class="o">=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">atype</span>
</span><span class='line'>        <span class="n">host</span> <span class="o">=</span> <span class="no">IPAddr</span><span class="o">.</span><span class="n">ntop</span> <span class="vi">@data</span><span class="o">[</span><span class="mi">4</span><span class="p">,</span> <span class="n">ip_length</span><span class="o">]</span>
</span><span class='line'>        <span class="n">port</span> <span class="o">=</span> <span class="vi">@data</span><span class="o">[</span><span class="mi">4</span> <span class="o">+</span> <span class="n">ip_length</span><span class="p">,</span> <span class="mi">2</span><span class="o">].</span><span class="n">unpack</span><span class="p">(</span><span class="s1">&#39;S&gt;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">first</span>
</span><span class='line'>        <span class="n">header_length</span> <span class="o">=</span> <span class="n">ip_length</span> <span class="o">+</span> <span class="mi">6</span>
</span><span class='line'>      <span class="k">when</span> <span class="mi">3</span>     <span class="c1"># domain name</span>
</span><span class='line'>        <span class="n">host</span> <span class="o">=</span> <span class="vi">@data</span><span class="o">[</span><span class="mi">5</span><span class="p">,</span> <span class="n">addr_length</span><span class="o">]</span>
</span><span class='line'>        <span class="n">port</span> <span class="o">=</span> <span class="vi">@data</span><span class="o">[</span><span class="mi">5</span> <span class="o">+</span> <span class="n">addr_length</span><span class="p">,</span> <span class="mi">2</span><span class="o">].</span><span class="n">unpack</span><span class="p">(</span><span class="s1">&#39;S&gt;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">first</span>
</span><span class='line'>        <span class="n">header_length</span> <span class="o">=</span> <span class="n">addr_length</span> <span class="o">+</span> <span class="mi">7</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="n">panic</span> <span class="ss">:address_type_not_supported</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">case</span> <span class="n">cmd</span>
</span><span class='line'>      <span class="k">when</span> <span class="mi">1</span>
</span><span class='line'>        <span class="n">send_data</span> <span class="n">reply_data</span><span class="p">(</span><span class="ss">:success</span><span class="p">)</span>
</span><span class='line'>        <span class="vi">@connection</span> <span class="o">=</span> <span class="no">EventMachine</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="no">REMOTE_SERVER_HOST</span><span class="p">,</span> <span class="no">REMOTE_SERVER_PORT</span><span class="p">,</span> <span class="no">LocalConnection</span><span class="p">)</span>
</span><span class='line'>        <span class="vi">@connection</span><span class="o">.</span><span class="n">server</span> <span class="o">=</span> <span class="nb">self</span>
</span><span class='line'>        <span class="vi">@connection</span><span class="o">.</span><span class="n">send_encoded_data</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">#{</span><span class="n">host</span><span class="si">}</span><span class="s2">:</span><span class="si">#{</span><span class="n">port</span><span class="si">}</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>        <span class="vi">@connection</span><span class="o">.</span><span class="n">send_encoded_data</span><span class="p">(</span><span class="vi">@data</span><span class="o">[</span><span class="n">header_length</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="o">]</span><span class="p">)</span>
</span><span class='line'>        <span class="n">clear_data</span>
</span><span class='line'>        <span class="no">Fiber</span><span class="o">.</span><span class="n">yield</span>
</span><span class='line'>      <span class="k">when</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span>  <span class="c1"># bind, udp</span>
</span><span class='line'>        <span class="n">panic</span> <span class="ss">:command_not_supported</span>
</span><span class='line'>      <span class="k">else</span>
</span><span class='line'>        <span class="n">panic</span> <span class="ss">:command_not_supported</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1"># +----+-----+-------+------+----------+----------+</span>
</span><span class='line'>    <span class="c1"># |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |</span>
</span><span class='line'>    <span class="c1"># +----+-----+-------+------+----------+----------+</span>
</span><span class='line'>    <span class="c1"># | 1  |  1  | X&#39;00&#39; |  1   | Variable |    2     |</span>
</span><span class='line'>    <span class="c1"># +----+-----+-------+------+----------+----------+</span>
</span><span class='line'>    <span class="k">def</span> <span class="nf">reply_data</span><span class="p">(</span><span class="n">type</span><span class="p">)</span>
</span><span class='line'>      <span class="vi">@replies_hash</span> <span class="o">||=</span> <span class="k">begin</span>
</span><span class='line'>        <span class="p">{</span>
</span><span class='line'>          <span class="ss">success</span><span class="p">:</span>                    <span class="mi">0</span><span class="p">,</span>
</span><span class='line'>          <span class="ss">command_not_supported</span><span class="p">:</span>      <span class="mi">7</span><span class="p">,</span>
</span><span class='line'>          <span class="ss">address_type_not_supported</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span>
</span><span class='line'>        <span class="p">}</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="o">[</span><span class="n">k</span><span class="p">,</span> <span class="p">(</span><span class="s2">&quot;</span><span class="se">\x05</span><span class="si">#{</span><span class="o">[</span><span class="n">v</span><span class="o">].</span><span class="n">pack</span><span class="p">(</span><span class="s1">&#39;C&#39;</span><span class="p">)</span><span class="si">}</span><span class="se">\x00\x01\x00\x00\x00\x00\x00\x00</span><span class="s2">&quot;</span><span class="p">)</span><span class="o">]</span> <span class="p">}</span><span class="o">.</span><span class="n">to_h</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>      <span class="vi">@replies_hash</span><span class="o">[</span><span class="n">type</span><span class="o">]</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">clear_data</span>
</span><span class='line'>      <span class="vi">@data</span> <span class="o">=</span> <span class="kp">nil</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">panic</span><span class="p">(</span><span class="n">reply_type</span><span class="p">)</span>
</span><span class='line'>      <span class="n">send_data</span> <span class="n">reply_data</span><span class="p">(</span><span class="n">reply_type</span><span class="p">)</span>
</span><span class='line'>      <span class="no">Fiber</span><span class="o">.</span><span class="n">yield</span> <span class="kp">true</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="no">EventMachine</span><span class="o">.</span><span class="n">run</span> <span class="k">do</span>
</span><span class='line'>  <span class="nb">puts</span> <span class="s2">&quot;Start socks5 at </span><span class="si">#{</span><span class="no">LOCAL_SERVER_HOST</span><span class="si">}</span><span class="s2">:</span><span class="si">#{</span><span class="no">LOCAL_SERVER_PORT</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'>  <span class="no">EventMachine</span><span class="o">.</span><span class="n">start_server</span><span class="p">(</span><span class="no">LOCAL_SERVER_HOST</span><span class="p">,</span> <span class="no">LOCAL_SERVER_PORT</span><span class="p">,</span> <span class="no">LocalServer</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<ul>
<li>SOCKS5 の handshake をやるとき連続でデータのやり取りをするから、ここでは <a href="http://ruby-doc.org/core-2.2.3/Fiber.html">Fiber</a> を使えば効率よくかつかっこ良く実装できます。</li>
<li>アクセスがきたら、SOCKS のバージョンは５だったら <code>\x05\x00</code> を返します。（認証いらないから、NMETHODS と METHODS は無視）</li>
<li>次にコマンドのデータがきます。仕様通りホストとポートを解析します。

<ul>
<li>急いで書いたので、TCP しか実装していません。(´Д｀)</li>
</ul>
</li>
<li>解析したホストとポートと転送したいデータをリモートサーバーに送ります。

<ul>
<li>shadowsocks はローカルからリモートへ転送する時も SOCKS5 に従って実装してます。多分リモートサーバーの間に互換性をもたらすためです。こちらはシンプルのため、下記の形でデータを送ります。</li>
<li><code>&lt;HOST&gt;:&lt;PORT&gt;\nDATA...</code></li>
</ul>
</li>
</ul>


<h3>リモートサーバー</h3>

<p>ローカルサーバーに比べたらすごくシンプルなものです。<br/>
上記のホストとポートを取り出し、目標サーバーに接続し、データの部分をそのまま送ります。<br/>
最後は帰ってきたレスポンスを逆の経路でブラウザに返します。</p>

<figure class='code'><figcaption><span>remote.rb</span><a href='https://github.com/cctiger36/socks-tunnel-demo/blob/master/remote.rb'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s2">&quot;eventmachine&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="no">REMOTE_SERVER_PORT</span> <span class="o">=</span> <span class="s2">&quot;8082&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">RemoteConnection</span> <span class="o">&lt;</span> <span class="no">EventMachine</span><span class="o">::</span><span class="no">Connection</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:server</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">receive_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@server</span><span class="o">.</span><span class="n">send_encoded_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">unbind</span>
</span><span class='line'>    <span class="vi">@server</span><span class="o">.</span><span class="n">close_connection_after_writing</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">RemoteServer</span> <span class="o">&lt;</span> <span class="no">EventMachine</span><span class="o">::</span><span class="no">Connection</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">post_init</span>
</span><span class='line'>    <span class="vi">@buffer</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">send_encoded_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="k">return</span> <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">nil?</span> <span class="o">||</span> <span class="n">data</span><span class="o">.</span><span class="n">length</span> <span class="o">==</span> <span class="mi">0</span>
</span><span class='line'>    <span class="c1"># TODO: encode data</span>
</span><span class='line'>    <span class="n">send_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">receive_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span><span class='line'>    <span class="c1"># TODO: decode data</span>
</span><span class='line'>    <span class="k">if</span> <span class="vi">@buffer</span>
</span><span class='line'>      <span class="vi">@buffer</span> <span class="o">&lt;&lt;</span> <span class="n">data</span>
</span><span class='line'>      <span class="n">addr</span><span class="p">,</span> <span class="n">rest</span> <span class="o">=</span> <span class="vi">@buffer</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">rest</span> <span class="o">&amp;&amp;</span> <span class="n">rest</span><span class="o">.</span><span class="n">length</span> <span class="o">&gt;</span> <span class="mi">0</span>
</span><span class='line'>        <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">addr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;:&quot;</span><span class="p">)</span>
</span><span class='line'>        <span class="n">port</span> <span class="o">=</span> <span class="n">port</span><span class="o">.</span><span class="n">nil?</span> <span class="p">?</span> <span class="mi">80</span> <span class="p">:</span> <span class="n">port</span><span class="o">.</span><span class="n">to_i</span>
</span><span class='line'>        <span class="vi">@connection</span> <span class="o">=</span> <span class="no">EventMachine</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="no">RemoteConnection</span><span class="p">)</span>
</span><span class='line'>        <span class="vi">@connection</span><span class="o">.</span><span class="n">server</span> <span class="o">=</span> <span class="nb">self</span>
</span><span class='line'>        <span class="vi">@connection</span><span class="o">.</span><span class="n">send_data</span><span class="p">(</span><span class="n">rest</span><span class="p">)</span> <span class="k">if</span> <span class="n">rest</span><span class="o">.</span><span class="n">length</span> <span class="o">&gt;</span> <span class="mi">0</span>
</span><span class='line'>        <span class="vi">@buffer</span> <span class="o">=</span> <span class="kp">nil</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>    <span class="k">else</span>
</span><span class='line'>      <span class="vi">@connection</span><span class="o">.</span><span class="n">send_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="k">if</span> <span class="n">data</span> <span class="o">&amp;&amp;</span> <span class="n">data</span><span class="o">.</span><span class="n">length</span> <span class="o">&gt;</span> <span class="mi">0</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">rescue</span>
</span><span class='line'>    <span class="vi">@connection</span><span class="o">.</span><span class="n">close_connection</span> <span class="k">if</span> <span class="vi">@connection</span>
</span><span class='line'>    <span class="n">close_connection</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">unbind</span>
</span><span class='line'>    <span class="vi">@connection</span><span class="o">.</span><span class="n">close_connection</span> <span class="k">if</span> <span class="vi">@connection</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="no">EventMachine</span><span class="o">.</span><span class="n">run</span> <span class="k">do</span>
</span><span class='line'>  <span class="nb">puts</span> <span class="s2">&quot;Starting server at 0.0.0.0:</span><span class="si">#{</span><span class="no">REMOTE_SERVER_PORT</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'>  <span class="no">EventMachine</span><span class="o">.</span><span class="n">start_server</span><span class="p">(</span><span class="s1">&#39;0.0.0.0&#39;</span><span class="p">,</span> <span class="no">REMOTE_SERVER_PORT</span><span class="p">,</span> <span class="no">RemoteServer</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h3>使い方</h3>

<p>リポジトリはこちらに上げました。<a href="https://github.com/cctiger36/socks-tunnel-demo">socks-tunnel-demo</a></p>

<ul>
<li>まずは一番上のホストとポートを設定します。</li>
<li>ローカルで <code>bundle exec ruby local.rb</code> を実行します。</li>
<li>リモートサーバーで <code>bundle exec ruby remote.rb</code> を実行します。</li>
<li>ブラウザのプロキシの設定にローカルサーバーを設定します。Mac ならこんな感じです。
<img src="http://cctiger36.github.io/images/mac-proxy-settings.png"></li>
</ul>


<p>これでブラウザはプロキシ経由で外にアクセスできるはずです。</p>

<h3>TODO</h3>

<p>ここまで作ったものは実際には全く使いものにならないです。orz</p>

<p>何故なら急いで書いたから、肝心な暗号化の部分はまだ実装されていません（TODO が書いてるところ）。
今のローカルからリモートへの通信は Firewall に丸見えです。簡単に探知され、ゲームオーバーになります。</p>

<p>暗号化については連休中で補完できればと思います。本当に申し訳ございません。m(＿ ＿)m</p>

<h2>明日</h2>

<p>【その2】ドリコム Adevent Calendar 2015 25日目は ericinderbuchtvontokio さんです。</p>
]]></content>
  </entry>
  
</feed>
