【任務】
需要将某個網絡端口轉發到另一個主機(forwarding),但可能會是不同的端口(redirecting)。
【解決方案】
兩個使用threading和socket子產品的類就能完成我們需要的端口轉發和重定向。
<code>#encoding=utf8</code>
<code>#author: walker摘自《Python Cookbook(2rd)》</code>
<code>#date: 2015-06-11</code>
<code>#function: 網絡端口的轉發和重定向(适用于python2/python3)</code>
<code>import</code> <code>sys, socket, time, threading</code>
<code>LOGGING </code><code>=</code> <code>True</code>
<code>loglock </code><code>=</code> <code>threading.Lock()</code>
<code>#列印日志到标準輸出</code>
<code>def</code> <code>log(s, </code><code>*</code><code>a):</code>
<code> </code><code>if</code> <code>LOGGING:</code>
<code> </code><code>loglock.acquire()</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>print</code><code>(</code><code>'%s:%s'</code> <code>%</code> <code>(time.ctime(), (s </code><code>%</code> <code>a)))</code>
<code> </code><code>sys.stdout.flush()</code>
<code> </code><code>finally</code><code>:</code>
<code> </code><code>loglock.release()</code>
<code> </code>
<code>class</code> <code>PipeThread(threading.Thread):</code>
<code> </code><code>pipes </code><code>=</code> <code>[] </code><code>#靜态成員變量,存儲通訊的線程編号</code>
<code> </code><code>pipeslock </code><code>=</code> <code>threading.Lock()</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, source, sink):</code>
<code> </code><code>#Thread.__init__(self) #python2.2之前版本适用</code>
<code> </code><code>super</code><code>(PipeThread, </code><code>self</code><code>).__init__()</code>
<code> </code><code>self</code><code>.source </code><code>=</code> <code>source</code>
<code> </code><code>self</code><code>.sink </code><code>=</code> <code>sink</code>
<code> </code><code>log(</code><code>'Creating new pipe thread %s (%s -> %s)'</code><code>, </code>
<code> </code><code>self</code><code>, source.getpeername(), sink.getpeername())</code>
<code> </code><code>self</code><code>.pipeslock.acquire()</code>
<code> </code><code>self</code><code>.pipes.append(</code><code>self</code><code>)</code>
<code> </code><code>self</code><code>.pipeslock.release()</code>
<code> </code><code>pipes_now </code><code>=</code> <code>len</code><code>(</code><code>self</code><code>.pipes)</code>
<code> </code><code>log(</code><code>'%s pipes now active'</code><code>, pipes_now)</code>
<code> </code><code>def</code> <code>run(</code><code>self</code><code>):</code>
<code> </code><code>while</code> <code>True</code><code>:</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>data </code><code>=</code> <code>self</code><code>.source.recv(</code><code>1024</code><code>)</code>
<code> </code><code>if</code> <code>not</code> <code>data:</code>
<code> </code><code>break</code>
<code> </code><code>self</code><code>.sink.send(data)</code>
<code> </code><code>except</code><code>:</code>
<code> </code><code>break</code>
<code> </code><code>log(</code><code>'%s terminating'</code><code>, </code><code>self</code><code>) </code>
<code> </code><code>self</code><code>.pipes.remove(</code><code>self</code><code>)</code>
<code> </code><code>pipes_left </code><code>=</code> <code>len</code><code>(</code><code>self</code><code>.pipes)</code>
<code> </code><code>log(</code><code>'%s pipes still active'</code><code>, pipes_left)</code>
<code> </code>
<code>class</code> <code>Pinhole(threading.Thread):</code>
<code> </code><code>def</code> <code>__init__(</code><code>self</code><code>, port, newhost, newport):</code>
<code> </code><code>super</code><code>(Pinhole, </code><code>self</code><code>).__init__()</code>
<code> </code><code>log(</code><code>'Redirecting: localhost: %s->%s:%s'</code><code>, port, newhost, newport)</code>
<code> </code><code>self</code><code>.newhost </code><code>=</code> <code>newhost</code>
<code> </code><code>self</code><code>.newport </code><code>=</code> <code>newport</code>
<code> </code><code>self</code><code>.sock </code><code>=</code> <code>socket.socket(socket.AF_INET, socket.SOCK_STREAM)</code>
<code> </code><code>self</code><code>.sock.bind(('', port))</code>
<code> </code><code>self</code><code>.sock.listen(</code><code>5</code><code>) </code><code>#參數為timeout,機關為秒</code>
<code> </code><code>newsock, address </code><code>=</code> <code>self</code><code>.sock.accept()</code>
<code> </code><code>log(</code><code>'Creating new session for %s:%s'</code><code>, </code><code>*</code><code>address)</code>
<code> </code><code>fwd </code><code>=</code> <code>socket.socket(socket.AF_INET, socket.SOCK_STREAM)</code>
<code> </code><code>fwd.connect((</code><code>self</code><code>.newhost, </code><code>self</code><code>.newport))</code>
<code> </code><code>PipeThread(newsock, fwd).start() </code><code>#正向傳送</code>
<code> </code><code>PipeThread(fwd, newsock).start() </code><code>#逆向傳送</code>
<code>if</code> <code>__name__ </code><code>=</code><code>=</code> <code>'__main__'</code><code>:</code>
<code> </code><code>print</code><code>(</code><code>'Starting Pinhole port fowarder/redirector'</code><code>)</code>
<code> </code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>port </code><code>=</code> <code>int</code><code>(sys.argv[</code><code>1</code><code>])</code>
<code> </code><code>newhost </code><code>=</code> <code>sys.argv[</code><code>2</code><code>]</code>
<code> </code><code>newport </code><code>=</code> <code>int</code><code>(sys.argv[</code><code>3</code><code>])</code>
<code> </code><code>except</code> <code>IndexError:</code>
<code> </code><code>newport </code><code>=</code> <code>port</code>
<code> </code><code>except</code> <code>(ValueError, IndexError):</code>
<code> </code><code>print</code><code>(</code><code>'Usage: %s port newhost [newport]'</code> <code>%</code> <code>sys.argv[</code><code>0</code><code>])</code>
<code> </code><code>sys.exit(</code><code>1</code><code>)</code>
<code> </code><code>#sys.stdout = open('pinhole.log', 'w') #将日志寫入檔案</code>
<code> </code><code>Pinhole(port, newhost, newport).start()</code>
【讨論】
當你在管理一個網絡時,即使是一個很小的網絡,端口轉發和重定向的功能有時也能給你很大的幫助。一些不在你的控制之下的應用或者服務可能是以硬連接配接的方式接入到某個特定的伺服器的位址或端口。通過插入轉發和重定向,你就能将對應用的連接配接請求發送到其他更合适的主機或端口上。
本文轉自walker snapshot部落格51CTO部落格,原文連結http://blog.51cto.com/walkerqt/1660749如需轉載請自行聯系原作者
RQSLT