最近在做有关 python 的项目,工作的网络环境如下:
PC1是我所使用的开发机,处于公司内网中即都与公司10.239.58.1交换机相连,PC2有两张网卡,第一张连接10.239.58.1,第二张连接192.168.122.1,操作系统为win8.1,PC3-PC6都是连入192.168.122.1,组成自己的局域网,而且操作系统均为Fedora LINUX。在PC1上开发的程序需要依赖PC3-PC6才能运行(依赖HTTP server 和 SSH登陆配置),所以整个流程是,我需要remote到PC2上,在PC2上进行开发测试,由于PC2是windows系统,不能同时多人remote,因此当我在使用PC2时其他同事若要想访问PC3-PC5他们要去机房,那环境可想而知,或者我退出他们使用。这对于我来说太麻烦,多人共享一个设备很不方便,我决定做一个转发工具,用于转发HTTP 报文和对SSH的22端口进行转发。由于刚刚接触python,项目用的也是python,决定用python做这件事,还能再项目之余锻炼一下。
由于SSH使用的协议和HTTP使用的协议都是在TCP/IP协议之上,所以我就想到了在socket层上进行数据流转发。代码如下:
# -*- coding: utf-8 -*- from socket import * import threading import Queue # test in python 2.7 # a list of local port mapped to machine ssh_server_list = [{"host": '10.239.58.102', "port": 8102, "ip": "192.168.122.102"}, {"host": '10.239.58.102', "port": 8103, "ip": "192.168.122.103"}, {"host": '10.239.58.102', "port": 8101, "ip": "192.168.122.101"}, {"host": '10.239.58.102', "port": 8104, "ip": "192.168.122.104"}] # sync all the threads in each of tunnel running_flag = [] # receive buffSize buffer_size = 2048 def get_data_from_ssh_server(rev_msg, tcp_socket, flag): """ :param rev_msg: a queue buffer of message need to be send to SSH client :param tcp_socket: instance of socket used for sending data :param flag: control this function :return: null """ while running_flag[flag]: data = tcp_socket.recv(buffer_size) if len(data): rev_msg.put(str(data)) else: running_flag[flag] = False def send_data_to_ssh_client(rev_msg, tcp_socket, flag): """ :param rev_msg: a queue buffer of message need to be send to SSH client :param tcp_socket: instance of socket used for sending data :param flag: control this function :return: null """ while running_flag[flag]: try: data = rev_msg.get(timeout=10) data = tcp_socket.send(str(data)) except: pass def get_data_from_ssh_client(send_msg, tcp_socket, flag): """ :param send_msg: a queue buffer of message need to be send to SSH server in each machine :param tcp_socket: instance of socket used for sending data :param flag: control this function :return: null """ while running_flag[flag]: data = tcp_socket.recv(buffer_size) if len(data): send_msg.put(str(data)) else: running_flag[flag] = False def send_data_to_ssh_server(send_msg, tcp_socket, flag): """ :param send_msg: a queue buffer of message need to be send to SSH server in each machine :param tcp_socket: instance of socket used for sending data :param flag: control this function :return: null """ while running_flag[flag]: try: data = send_msg.get(timeout=10) data = tcp_socket.send(str(data)) except: pass def handle_connections(host, ip, port): """ :param host: local ip :param ip: which machine the data will be forwarded :param port: local port :return: null """ ssh_client_socket = socket(AF_INET, SOCK_STREAM) ssh_client_socket.bind((host, port)) # listen 10 client ssh_client_socket.listen(10) while True: ssh_client_side, address = ssh_client_socket.accept() # two queue for keeping data from SSH client and SSH server buffer_send = Queue.Queue() buffer_rev = Queue.Queue() ssh_server_side = socket(AF_INET, SOCK_STREAM) ssh_server_side.connect((ip, 22)) flag = True running_flag.append(flag) rev1 = threading.Thread(target=get_data_from_ssh_server, args=(buffer_rev, ssh_server_side, len(running_flag) - 1)) rev2 = threading.Thread(target=send_data_to_ssh_client, args=(buffer_rev, ssh_client_side, len(running_flag) - 1)) send1 = threading.Thread(target=get_data_from_ssh_client, args=(buffer_send, ssh_client_side, len(running_flag) - 1)) send2 = threading.Thread(target=send_data_to_ssh_server, args=(buffer_send, ssh_server_side, len(running_flag) - 1)) rev1.start() rev2.start() send1.start() send2.start() if __name__ == "__main__": print("start SSH forward server") thread_pool = [] for i in ssh_server_list: print("ssh mapping " + i["host"] + ":" + str(i["port"]) + " => " + i["ip"] + ":22") t = threading.Thread(target=handle_connections, args=(i["host"], i["ip"], i["port"])) thread_pool.append(t) t.start() print("initialize SSH forward server done")