hpsocket做一个tcp转发器
By
money
at 2021-11-13 • 0人收藏 • 1569人看过
没智能提示的库就是垃圾,哈哈,这个库缺少灵魂。
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的玩法,有些用法不是很明白。
登录后方可回帖
网络相关的还没研究过
, 谢谢分享, 学习了.