hpsocket做一个tcp转发器
By
money
at 2021-11-13 • 0人收藏 • 1396人看过
没智能提示的库就是垃圾,哈哈,这个库缺少灵魂。
import hpsocket.tcpAgent; import hpsocket.tcpServer; import thread.event; namespace hpsocket; class tcpProxy{ /* config={ localIP="0.0.0.0"; localPort=99; proxy={ ip=""; //固定的转发IP和端口 port=0; handleRecv=function(direction, str){};//返回修改后的内容 发送 handleConnection=function(evt, arg, extraTab){}//evt:accept返回转发的ip port ,evt:close不需要返回 }; } */ ctor( config){ config.localIP:="0.0.0.0"; if(!config.localPort){ error("localPort不能为空"); } if(!config.proxy){ error("config 缺少proxy参数"); } if(config.proxy.handleRecv and type(config.proxy.handleRecv)!=type.function){ return null, "handleRecv必须为function"; } if(config.proxy.handleConnection){ if(type(config.proxy.handleConnection)!=type.function){ return null, "handleConnection必须为function"; } }elseif(!config.proxy.ip or !config.proxy.port) { return null, "ip,port不能为空"; } this.agent = ..hpsocket.tcpAgent(); this.server = ..hpsocket.tcpServer(); this.server.setAcceptSocketCount(2000) this.agent.onThreadCreated = function(){ import console; import thread.event; import hpsocket.tcpServer; import thread.command; import wsock; import time.performance; class context{ int serverid; int agentid; int index; int ip; WORD port; } log = function(...){ thread.lock("proxy_log") ..console.dump(...) thread.unlock("proxy_log") } _hpTcpServer = hpsocket.tcpServer(_serverSocket); } this.agent.threadGlobal = { _serverSocket = this.server.pSocket; _config = config; hasHandleRecv = config.proxy and type(config.proxy.handleRecv)==type.function; hasHandleConnection = config.proxy and type(config.proxy.handleConnection)==type.function; handleConnection = config.proxy.handleConnection; handleRecv = config.proxy.handleRecv; ip = config.proxy.ip; port = config.proxy.port; } //连接成功触发 this.agent.onConnect = function(hpTcpAgent,connId){ //这里一定要等待extra while(!hpTcpAgent.getConnectionExtra(connId)){ sleep(1) } //给server发送连接事件信号 var evt = thread.event("agent_"++connId) evt.set() } this.agent.onReceive = function(hpTcpAgent,connId,pData,length){ var exta = hpTcpAgent.getConnectionExtra(connId); var tab=context(); tab = ..raw.convert(exta,tab) //转发数据给server,通过server转转发到近端 //handleRecv函数可以修改发送前的数据 if(handleRecv){ var data = ..raw.tostring(pData,1,length) data = handleRecv("remoteToLocal", data, tab) _hpTcpServer.send(tab.serverid, data, #data) }else { _hpTcpServer.send(tab.serverid, pData, length) } } this.agent.onClose = function(hpTcpAgent,connId,enOperation,errCode){ var extra = hpTcpAgent.getConnectionExtra(connId); if(extra){ var tab = context(); tab = ..raw.convert(extra,tab) if(handleConnection){ handleConnection("close", errCode, tab) } //非正常关闭,server可能还在等待agent连接,给server发送信号 var evt = thread.event("agent_"++connId) evt.set() //断开对应的server连接 _hpTcpServer.disconnect(tab.serverid) }else { log("agent.onClose,无exta", connId) } } this.server.onThreadCreated = function(){ import console; import thread.event; import hpsocket.tcpAgent; import thread.command; import wsock; class context{ int serverid; int agentid; int index; int ip; WORD port; } log = function(...){ thread.lock("proxy_log") ..console.dump(...) thread.unlock("proxy_log") } _hpTcpAgent = hpsocket.tcpAgent(_agentSocket) } this.server.threadGlobal = { _agentSocket = this.agent.pSocket; _config = config; hasHandleRecv = config.proxy and type(config.proxy.handleRecv)==type.function; hasHandleConnection = config.proxy and type(config.proxy.handleConnection)==type.function; handleConnection = config.proxy.handleConnection; handleRecv = config.proxy.handleRecv; ip = config.proxy.ip; port = config.proxy.port; } this.server.onShutdown = function(hpTcpServer){ //断开所有agent连接 _hpTcpAgent.disconnectSilenceConnections(1,true) } this.server.onAccept = function(hpTcpServer,connId,pClient){ //本地端口收到连接后 agent立即建一个远端连接 var ip,port,index if(hasHandleConnection){ ip, port, index = handleConnection("accept") }else { ip, port = ip, port; } if(ip and port){ var tab=context(); tab.serverid = connId; tab.index = index:0; tab.ip = wsock.htonl(..wsock.inet_addr( ip )) tab.port = port; var pExtra = hpTcpServer.getConnectionExtra(connId) pExtra = ..raw.realloc(..raw.sizeof(tab), pExtra, s) hpTcpServer.setConnectionExtra(connId, pExtra) var id = _hpTcpAgent.connect(ip, port); if(id){ _hpTcpAgent.setConnectionExtra(id, pExtra) tab.agentid = id; ..raw.convert(tab, pExtra); var evt2 = thread.event("agent_"++id); if(!evt2.wait(2000)){ evt2.close() _hpTcpAgent.disconnect(id, true) return 2; } evt2.close() }else { return 2; } } return 0; } this.server.onReceive = function(hpTcpServer,connId,pData,length){ var exta = hpTcpServer.getConnectionExtra(connId); if(exta){ var tab=context(); tab = ..raw.convert(exta,tab) //转发数据给agent,通过agent转换到远端 //handleRecv函数可以修改发送前的数据 if(handleRecv){ var data = ..raw.tostring(pData,1,length) data = handleRecv("localToRemote", data) _hpTcpAgent.send(tab.agentid, data, #data) }else { _hpTcpAgent.send(tab.agentid, pData, length) } }else { log("server.onReceive,无agent", connId) return 2; } } this.server.onClose = function(hpTcpServer,connId,enOperation,errCode){ var exta = hpTcpServer.getConnectionExtra(connId); if(exta){ var tab=context(); tab = ..raw.convert(exta,tab) //断开对应的agent连接 _hpTcpAgent.disconnect(tab.agentid) //清空extra ..raw.realloc(0, exta) }else { log("server.onClose,无exta", connId) } } this.server.onPrepareListen = function(hpTcpServer,soListen){ //开始监听(重起监听)后,清理超时的agent连接 _hpTcpAgent.disconnectSilenceConnections(90000); } this.start = function(){ var err if(this.server.start(config.localIP,config.localPort)){ if(this.agent.start()){ return true; }else { err="agent启动失败" } }else { err="近端监听端口失败" } return false, err; } this.stop=function(){ this.agent.stop(); this.server.stop(); } }; }
库出来了,没有相关使用说明,做一个demo演示一下。用它做一个HttpProxy吧,动态转发挺方便的,安排上
server端:
import console; import win; import hpsocket.httpServer; import hpsocket.tcpProxy; console.open(); //换IP线程 thread.invoke( function(){ import inet.whttpEx; import console; import thread.command; import win; var proxies={}; var index=0; var proxyUse={}; //需要定制自己的fetch函数,主要实现从API中取IP出来备用 fetchProxy1=function(){ try{ var http = inet.whttpEx(); //这里用了一家代理IP,就不贴上来了 var str = http.get("http://www.3daili.top:9091/orderIp/********&jg=0&num=200&lx=A&proxy=http&gs=txt"); if(#str>100){ var tab = string.splitEx(str,"<\r\n>"); for(i=1;#tab;1){ table.push(proxies, tab[i]) } } } catch(e){ console.dump(e) } } var cmd = thread.command(); cmd.delProxy = function(proxy, reason){ console.dump("删除IP",proxy, reason) if(!string.indexOf(proxy,':')){ proxy = proxy+':' } var k = table.find(proxies, function(v, k, tab){ if(string.indexOf(v, proxy)){ return true; } }) if(k){ table.remove(proxies, k) } } cmd.getProxy = function(){ if(#proxies<20){ fetchProxy1() } if(#proxies){ index++; if(index>#proxies){ index=1 } var proxy = proxies[index] if(proxy){ if(!proxyUse[proxy]){ proxyUse[proxy]=1 }else { proxyUse[proxy] = proxyUse[proxy]+1 } //限制同一IP只使用5次 if(proxyUse[proxy]>5){ table.removeByValue(proxies, proxy) } } //console.dump("取出IP",proxy) return proxy; } } import win.timer; var timer = win.timer(winform,10000); timer.onTimer = function(){ var http = inet.whttpEx(); http.post(whiteurl, "") } timer.enable(); fetchProxy1() win.loopMessage() } ) handleConnection = function(evt, arg, tab){ if(evt == 'accept'){ var proxy = thread.command.getProxy(); if(#proxy){ var arr = string.split(proxy, ':') //return "192.168.32.1", 5000; return arr[1], tonumber(arr[2]) } }elseif(evt == 'close'){ if(arg){ var ip = wsock.inet_ntoa(wsock.ntohl(tab.ip)) var port = tab.port; thread.command.delProxy(string.format("%s:%d", ip, port), "IP失效"); } } } handleRecv = function(evt, data, tab){ //http还好,可以拦截处理,如果是HTTPS就不行了,所以基本上这里判断是没什么用的 //所以在下面另开了一个8082端口专用于删除不可用的IP if(evt == 'remoteToLocal'){ if(string.indexOf(data, 'Access Denied')){ var ip = wsock.inet_ntoa(wsock.ntohl(tab.ip)) var port = tab.port; thread.command.delProxy(string.format("%s:%d", ip, port), "IP限制"); } } return data; } var ser,err = hpsocket.tcpProxy({ localIP="0.0.0.0"; localPort=8081; proxy={ ip=""; port=0; //handleRecv=handleRecv; handleConnection=handleConnection }; }) console.dump(err) console.dump(ser.start()) //另开一个端口,开放一个用于删除指定IP的功能 var hpHttpServer = hpsocket.httpServer(); hpHttpServer.onThreadCreated = function(){ import inet.whttpEx; import thread.command; } hpHttpServer.onHeadersComplete = function(hpHttpServer,connId){ hpHttpServer.reallocString(connId,hpHttpServer.getContentLength(connId)) } hpHttpServer.onBody = function(hpHttpServer,connId,pData,len){ hpHttpServer.appendString(connId,pData,len) } hpHttpServer.onMessageComplete = function(hpHttpServer,connId){ var proxy = hpHttpServer.getString(connId); if(#proxy){ thread.command.delProxy(proxy, "IP限制"); } hpHttpServer.sendResponse(connId,"OK",{ ["Content-Type"] = "text/html; charset=UTF-8"; }); } hpHttpServer.start("0.0.0.0", 8082) win.loopMessage();
嗯,再来个简单的client测试一下
import console; import inet.whttp; import win; console.open(); //来吧,暴力测试一下 for(i=1;200;1){ thread.invoke( function(){ import inet.whttp; import console; for(i=1;999999;1){ var http = inet.whttp(,"HTTP://127.0.0.1:8081") console.dump(i, http.get("某个获取IP的地址")) } } ) } win.loopMessage()
就缺两张图了
嗯,好像哪里不对,没有安全验证啊?就这样吧
2 个回复 | 最后更新于 2023-03-27
感谢楼主的代码,想请教一下楼主这个库代码是怎么写出来的,有什么关于hpTcpServer完整的库写法可以参考吗?
class context{ int serverid; int agentid; int index; int ip; WORD port; }
比如库中上面这种结构体的定义,以及下面这样的使用方法
var tab=context(); tab.serverid = connId; tab.index = index:0; tab.ip = wsock.htonl(..wsock.inet_addr( ip )) tab.port = port; var pExtra = hpTcpServer.getConnectionExtra(connId) pExtra = ..raw.realloc(..raw.sizeof(tab), pExtra, s) hpTcpServer.setConnectionExtra(connId, pExtra)
为什么我就不知道应该这样写呢
最近也在学习hpTcpServer的玩法,有些用法不是很明白。
登录后方可回帖
网络相关的还没研究过, 谢谢分享, 学习了.