实际系统开发和项目测试过程中,有时需要对某个请求通过中间服务器进行转发。常见的是内网服务通过公共的外网机转发访问。
简介
实际系统开发和项目测试过程中,有时需要对某个请求通过中间服务器进行转发。常见的是内网服务通过公共的外网机转发访问。
转发架构
用户通过访问代理服务器,代理服务器去访问业务服务器,把数据转给用户。
实现方式
实现的方式有很多,这里对我使用过的方式做个简要的介绍。
方法一:socket监听转发
实际过程中可以根据服务器环境和自身技术栈自由定制。核心就是起个socket服务,监听来的请求,转发给目标服务器,将数据返回用户。
以python为例:
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
| import socket import threading
CFG_REMOTE_IP = '127.0.0.1' CFG_REMOTE_PORT = 8080 CFG_LOCAL_IP = '0.0.0.0' CFG_LOCAL_PORT = 80
PKT_BUFF_SIZE = 2048
def send_log(content): print content return
def tcp_mapping_worker(conn_receiver, conn_sender): while True: try: data = conn_receiver.recv(PKT_BUFF_SIZE) except Exception: send_log('Event: Connection closed.') break if not data: send_log('Info: No more data is received.') break try: conn_sender.sendall(data) except Exception: send_log('Error: Failed sending data.') break send_log('Info: Mapping > %s -> %s > %d bytes.' % (conn_receiver.getpeername(), conn_sender.getpeername(), len(data))) conn_receiver.close() conn_sender.close() return
def tcp_mapping_request(local_conn, remote_ip, remote_port): remote_conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: remote_conn.connect((remote_ip, remote_port)) except Exception: local_conn.close() send_log('Error: Unable to connect to the remote server.') return threading.Thread(target=tcp_mapping_worker, args=(local_conn, remote_conn)).start() threading.Thread(target=tcp_mapping_worker, args=(remote_conn, local_conn)).start() return
def tcp_mapping(remote_ip, remote_port, local_ip, local_port): local_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) local_server.bind((local_ip, local_port)) local_server.listen(5) send_log('Event: Starting mapping service on ' + local_ip + ':' + str(local_port) + ' ...') while True: try: (local_conn, local_addr) = local_server.accept() except KeyboardInterrupt, Exception: local_server.close() send_log('Event: Stop mapping service.') break threading.Thread(target=tcp_mapping_request, args=(local_conn, remote_ip, remote_port)).start() send_log('Event: Receive mapping request from %s:%d.' % local_addr) return
if __name__ == '__main__': tcp_mapping(CFG_REMOTE_IP, CFG_REMOTE_PORT, CFG_LOCAL_IP, CFG_LOCAL_PORT)
|
方法二:goreplay请求转发
需要下载对应的系统的goreplay可执行文件。
1
| $ ./goreplay --input-raw :8080 --output-http "http://192.168.1.100:80"
|
方法三:nginx反向代理
这是运维的常规操作,需要再服务器上安装对应的web容器,nginx、apache、tomcat等等。
以nginx为例:
1 2 3 4 5 6 7 8 9
| server { listen 8080; server_name www.test.com;
location / { proxy_pass http://127.0.0.1:80; index index.html index.htm index.jsp; } }
|
方法四:代理工具转发
大部分的代理工具都可以界面操作,进行请求转发,以charles为例。
设置方法:Tools > Map Remote > Add (记得启用)
结语
条条大路通罗马,同一个问题可能有N种解决方案。实际解决过程中可以根据自己当时的环境,来制定最优的解决方案。