可以监控应用对外的网络流量、分析协议、重定向、并针对每个协议进行修改,同时可以录制和回放。项目也得到了部门总监和其他leader的肯定,可以多花心思弄弄好。
因为项目的核心是一个Socks代理,通过这个代理捕获双方的流量,并进行后续的操作。
后来跟RednaxelaFX提问之后,确认了JVM是根据ClassCloader+package来确定一个包的,所以要使自己写的类能访问sun.nio
包的内容,必须使用Boostrap Classloader来加载。后来在javaagent里配置了相应参数,搞定!
配置Client
JDK的OIO是支持全局代理的,只需在JVM参数中配置-DsocksProxyHost=xxx -DsocksProxyPort=xxx
即可。遗憾的是,这个配置对NIO是不起作用的。
后来考虑过几种办法:
-
因为公司项目用到NIO的部分,主要也是通过netty做的。那么改netty的API,使其支持代理,是最简单的做法。使用netty构建一个socks client也是得心应手。但是这种做法不够彻底,且不具有通用性。
-
修改NIO的接口SocketChannel.open()的实现,使其返回一个可以使用代理的SocketChannel。这种方法最彻底,但是涉及到JDK一些底层API,有些还没有暴露出来,实现难度有点大。
后来决定采用方法2,顺便学习一下。
SelectorProviderImpl
、SocketChannelImpl
都是VM的私有API,只有下载JDK源码才能看到。下载openjdk源码后,在jdk/src/share/classes/
目录可找到。
SelectorProvider.provider()
是JDK自己的一个扩展点,会根据不同的OS选择不同的SelectorProvider,OSX是KQueue。尝试自己写了一个SocketChannel的子类,做一个全局代理,结果被SelectorImpl摆了一道,里面要求必须实现sun.nio.ch.SelChImpl
接口,而这个接口是包级可见的。
抱着侥幸心理,尝试将自己的新类写到sun.nio.ch
包下,结果编译通过,加载提示无法访问其父类接口sun.nio.ch.SelChImpl
,
后来跟RednaxelaFX提问之后,确认了JVM是根据ClassCloader+package来确定一个包的,所以要使自己写的类能访问sun.nio
包的内容,必须使用Boostrap Classloader来加载。后来在javaagent里配置了相应参数,搞定!