(如果你用oracle.odac并有什么VPN之类的话,其实就无需此文了)(转帖,请注明原创作者: 成都.廖长科 谢谢)
说明: 此文仅作技术讨论、学习为目的,请自行遵守相关法律,本文作者不承担责任后果.
环境: 局域网内网地址192.168.2.18上安装了oracle9,TNS端口1521,路由器虚拟服务转发1521端到此地址。想到这样的话,就可以SOHO了.
状态: (如果你知道oracle的1521端实际作用可跳过) 外网安了oracle客户端和odac,odac使用net方式,连接成功,并可取出数据。但是ora客户端连管理器的连接测试都通不过,发现连接测试时所连接的地址并非外网地址,变成了192.168.2.18(端口不是1521). 在内网中用PLSQLDeveloper连接后,发现登陆后的实际操作并非是连接1521端口,且有时会变换新端口
试手开始: 准备了Indy的MappedTCP环境, 过程如下: 1.client发送请求数据, 中间包含了"(HOST=xxxxx.xxxx.xxx)(PORT=4414)",其中HOST为ora连接管理器中配置的主机名,端口同样. 另外后面还有一个HOSP=当前机器的机器名 2.ora每次的命令封包, 头两个字节为Word(16位), 代表此次封包的总长度(注意也包含了Word自身), 第五个字节在第一次连接时为byte(1), 此后知道应该是命令号, 命令号的长度不清楚, sorry。命令号后的字节不清楚用途,但有时候是记录此次封包内下一段的字节长度(同样包含长度Word自身). 3.服务端收到后,1521端返回了命令号为byte(5)的命令,数据的确包含了新分配给客户端连接的端口和IP,OK了,改数据 修改思想:
1.在TIdMappedTCP基础上继承, 假设出口地址为4444, Mapped地址当然为192.168.2.18:1521, 2.Client发命令byte(1)时,保存客户端请求的地址,等会儿要返回给客户端的. 3.Server返命令byte(5)时"(HOST=192.168.2.18)(PORT=1031)",把HOST换为刚才保存的地址(也就是说叫客户端再连此IP的程序), 端口1031怎么办喃? 当然是保存起来,由Mapped程序连接, 客户端又连哪儿? 这样: 再内置个MappedTCP服务,Mapped到5号命令返回的Port, 出口地址嘛正好设个4447端. 所以还得把封包中PORT换为4447. 贴个修改包长度的代码: //changedPackage为已经换了HOST和PORT的string //注意了哈!!! ora封包大小虽为word, 但与delphi中的word相比, //其高位和低位正好是相反的, 得转换一下 // type psWord = ^tsWord; tsWord = packed record b1 : byte; b2 : byte; end; var ppp : PChar; begin wSize := Length(changedPackage); ppp := @LParm[1]; //反转delphi的word psWord(@wSize2).b2 := psWord(@wSize).b1; psWord(@wSize2).b1 := psWord(@wSize).b2; //写新的大小 Move(wSize2, ppp^, 2); //5号命令中子长度, 正好是第8位开始 Inc(ppp, 8); //读旧的大小再-10 move(ppp^, wSize2, 2); //写新的子长度, -10是把总长度占的两个字节算进去了的 wSize := wSize-10; psWord(@wSize2).b2 := psWord(@wSize).b1; psWord(@wSize2).b1 := psWord(@wSize).b2; Move(wSize2, ppp^, 2); 4.最后,被保存的1031端口怎么办? 可以把端口地址放到一个队列中,当客户端连接到4447端口,POP出一个端口和缓存的HOST, 作内置IdMappedTCP的MappedHost和MappedPort, 可以将BackMapped.OnConnect := BackConnect, 并在BackConnect中POP出缓存的Port, 因为:
procedure TIdMappedPortThread.OutboundConnect; Begin FOutboundClient := TIdTCPClient.Create(NIL); with TIdMappedPortTCP(Connection.Server) do begin try with TIdTcpClient(FOutboundClient) do begin Port := MappedPort; Host := MappedHost; end;//with DoLocalClientConnect(SELF); //这里执行OnConnect事件, 下面就会Connect了哈
TIdTcpClient(FOutboundClient).Connect(FConnectTimeOut); DoOutboundClientConnect(SELF); except on E: Exception do begin DoOutboundClientConnect(SELF,E); Connection.Disconnect; end; end;//trye end;//with End;
巧功告成: 此程序可以放到可以访问192.168.2.18地址的任意机器上, 程序只监听4444和4447两个端口, 因此,你可以到路由器中设置转发4444/4447两个端口(4444相当于1521端口, 1521端口本身只是作监听端口转发,不作登陆/SQL数据传送滴), 从此便可以远程外网连接ORA了,爽吧,加好密,小心被攻击。
多看看Indy的TIdMappedFTP对你有帮助, 此思想等于是用4447这个不变应了ora的万变端口. 但ORA有加密封包的功能, 加密后, 就得想办法解密了哈,我想还是可行滴!
了解更多 QQ:7896615