【任务】
需要将某个网络端口转发到另一个主机(forwarding),但可能会是不同的端口(redirecting)。
【解决方案】
两个使用threading和socket模块的类就能完成我们需要的端口转发和重定向。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
#encoding=utf8
#author: walker摘自《Python Cookbook(2rd)》
#date: 2015-06-11
#function: 网络端口的转发和重定向(适用于python2/python3)
import
sys, socket, time, threading
LOGGING
=
True
loglock
=
threading.Lock()
#打印日志到标准输出
def
log(s,
*
a):
if
LOGGING:
loglock.acquire()
try
:
print
(
'%s:%s'
%
(time.ctime(), (s
%
a)))
sys.stdout.flush()
finally
:
loglock.release()
class
PipeThread(threading.Thread):
pipes
=
[]
#静态成员变量,存储通讯的线程编号
pipeslock
=
threading.Lock()
def
__init__(
self
, source, sink):
#Thread.__init__(self) #python2.2之前版本适用
super
(PipeThread,
self
).__init__()
self
.source
=
source
self
.sink
=
sink
log(
'Creating new pipe thread %s (%s -> %s)'
,
self
, source.getpeername(), sink.getpeername())
self
.pipeslock.acquire()
try
:
self
.pipes.append(
self
)
finally
:
self
.pipeslock.release()
self
.pipeslock.acquire()
try
:
pipes_now
=
len
(
self
.pipes)
finally
:
self
.pipeslock.release()
log(
'%s pipes now active'
, pipes_now)
def
run(
self
):
while
True
:
try
:
data
=
self
.source.recv(
1024
)
if
not
data:
break
self
.sink.send(data)
except
:
break
log(
'%s terminating'
,
self
)
self
.pipeslock.acquire()
try
:
self
.pipes.remove(
self
)
finally
:
self
.pipeslock.release()
self
.pipeslock.acquire()
try
:
pipes_left
=
len
(
self
.pipes)
finally
:
self
.pipeslock.release()
log(
'%s pipes still active'
, pipes_left)
class
Pinhole(threading.Thread):
def
__init__(
self
, port, newhost, newport):
#Thread.__init__(self) #python2.2之前版本适用
super
(Pinhole,
self
).__init__()
log(
'Redirecting: localhost: %s->%s:%s'
, port, newhost, newport)
self
.newhost
=
newhost
self
.newport
=
newport
self
.sock
=
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self
.sock.bind(('', port))
self
.sock.listen(
5
)
#参数为timeout,单位为秒
def
run(
self
):
while
True
:
newsock, address
=
self
.sock.accept()
log(
'Creating new session for %s:%s'
,
*
address)
fwd
=
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
fwd.connect((
self
.newhost,
self
.newport))
PipeThread(newsock, fwd).start()
#正向传送
PipeThread(fwd, newsock).start()
#逆向传送
if
__name__
=
=
'__main__'
:
print
(
'Starting Pinhole port fowarder/redirector'
)
try
:
port
=
int
(sys.argv[
1
])
newhost
=
sys.argv[
2
]
try
:
newport
=
int
(sys.argv[
3
])
except
IndexError:
newport
=
port
except
(ValueError, IndexError):
print
(
'Usage: %s port newhost [newport]'
%
sys.argv[
0
])
sys.exit(
1
)
#sys.stdout = open('pinhole.log', 'w') #将日志写入文件
Pinhole(port, newhost, newport).start()
|
【讨论】
当你在管理一个网络时,即使是一个很小的网络,端口转发和重定向的功能有时也能给你很大的帮助。一些不在你的控制之下的应用或者服务可能是以硬连接的方式接入到某个特定的服务器的地址或端口。通过插入转发和重定向,你就能将对应用的连接请求发送到其他更合适的主机或端口上。
相关阅读:端口转发(Linux/Windows)
*** walker ***
本文转自walker snapshot博客51CTO博客,原文链接http://blog.51cto.com/walkerqt/1660749如需转载请自行联系原作者
RQSLT