diff --git a/README.md b/README.md
index c5151f2..49efa86 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# ja-netfilter v1.1.0
+# ja-netfilter v1.1.1
### A javaagent lib for network filter
diff --git a/pom.xml b/pom.xml
index d34ede2..cd7c9b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
io.zhile.research
ja-netfilter
- 1.1.0
+ 1.1.1
UTF-8
diff --git a/src/main/java/io/zhile/research/ja/netfilter/Dispatcher.java b/src/main/java/io/zhile/research/ja/netfilter/Dispatcher.java
index 5fbee17..1d83da6 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/Dispatcher.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/Dispatcher.java
@@ -1,7 +1,7 @@
package io.zhile.research.ja.netfilter;
import io.zhile.research.ja.netfilter.commons.DebugInfo;
-import io.zhile.research.ja.netfilter.transformers.MyTransformer;
+import io.zhile.research.ja.netfilter.plugin.MyTransformer;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
@@ -28,12 +28,20 @@ public class Dispatcher implements ClassFileTransformer {
}
public void addTransformers(List transformers) {
+ if (null == transformers) {
+ return;
+ }
+
for (MyTransformer transformer : transformers) {
addTransformer(transformer);
}
}
public void addTransformers(MyTransformer[] transformers) {
+ if (null == transformers) {
+ return;
+ }
+
addTransformers(Arrays.asList(transformers));
}
@@ -54,7 +62,7 @@ public class Dispatcher implements ClassFileTransformer {
for (MyTransformer transformer : transformers) {
classFileBuffer = transformer.transform(className, classFileBuffer, order++);
}
- } catch (Exception e) {
+ } catch (Throwable e) {
DebugInfo.output("Transform class failed: " + e.getMessage());
}
} while (false);
diff --git a/src/main/java/io/zhile/research/ja/netfilter/Initializer.java b/src/main/java/io/zhile/research/ja/netfilter/Initializer.java
index f96250e..5532f14 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/Initializer.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/Initializer.java
@@ -21,7 +21,7 @@ public class Initializer {
try {
FilterConfig.setCurrent(new FilterConfig(ConfigParser.parse(configFile)));
- } catch (Exception e) {
+ } catch (Throwable e) {
DebugInfo.output(e.getMessage());
}
diff --git a/src/main/java/io/zhile/research/ja/netfilter/Launcher.java b/src/main/java/io/zhile/research/ja/netfilter/Launcher.java
index 9fb5de3..3729d5f 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/Launcher.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/Launcher.java
@@ -19,7 +19,7 @@ public class Launcher {
URI jarURI;
try {
jarURI = getJarURI();
- } catch (Exception e) {
+ } catch (Throwable e) {
DebugInfo.output("ERROR: Can not locate ja-netfilter jar file.");
return;
}
diff --git a/src/main/java/io/zhile/research/ja/netfilter/transformers/MyTransformer.java b/src/main/java/io/zhile/research/ja/netfilter/plugin/MyTransformer.java
similarity index 78%
rename from src/main/java/io/zhile/research/ja/netfilter/transformers/MyTransformer.java
rename to src/main/java/io/zhile/research/ja/netfilter/plugin/MyTransformer.java
index 5b2d6f8..6053739 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/transformers/MyTransformer.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugin/MyTransformer.java
@@ -1,4 +1,4 @@
-package io.zhile.research.ja.netfilter.transformers;
+package io.zhile.research.ja.netfilter.plugin;
public interface MyTransformer {
String getHookClassName();
diff --git a/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginEntry.java b/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginEntry.java
index 1c9bf75..b5bfd62 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginEntry.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginEntry.java
@@ -1,7 +1,6 @@
package io.zhile.research.ja.netfilter.plugin;
import io.zhile.research.ja.netfilter.models.FilterRule;
-import io.zhile.research.ja.netfilter.transformers.MyTransformer;
import java.util.List;
@@ -12,6 +11,8 @@ public interface PluginEntry {
String getName();
+ String getAuthor();
+
default String getVersion() {
return "v1.0.0";
}
diff --git a/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginManager.java b/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginManager.java
index b08a60c..dcbe405 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginManager.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugin/PluginManager.java
@@ -3,14 +3,15 @@ package io.zhile.research.ja.netfilter.plugin;
import io.zhile.research.ja.netfilter.Dispatcher;
import io.zhile.research.ja.netfilter.commons.DebugInfo;
import io.zhile.research.ja.netfilter.models.FilterConfig;
-import io.zhile.research.ja.netfilter.transformers.HttpClientTransformer;
-import io.zhile.research.ja.netfilter.transformers.InetAddressTransformer;
-import io.zhile.research.ja.netfilter.transformers.MyTransformer;
+import io.zhile.research.ja.netfilter.plugins.dns.DNSFilterPlugin;
+import io.zhile.research.ja.netfilter.plugins.url.URLFilterPlugin;
import io.zhile.research.ja.netfilter.utils.StringUtils;
import java.io.File;
import java.lang.instrument.Instrumentation;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
@@ -29,46 +30,63 @@ public class PluginManager {
}
public void loadPlugins(Instrumentation inst, File currentDirectory) {
- File pluginsDirectory = new File(currentDirectory, PLUGINS_DIR);
- if (!pluginsDirectory.exists() || !pluginsDirectory.isDirectory()) {
- return;
- }
-
- File[] pluginFiles = pluginsDirectory.listFiles((d, n) -> n.endsWith(".jar"));
- if (null == pluginFiles) {
- return;
- }
-
- Dispatcher.getInstance().addTransformers(new MyTransformer[]{ // built-in transformers
- new HttpClientTransformer(),
- new InetAddressTransformer()
- });
-
- for (File pluginFile : pluginFiles) {
+ for (Class extends PluginEntry> klass : getAllPluginClasses(inst, currentDirectory)) {
try {
- JarFile jarFile = new JarFile(pluginFile);
- Manifest manifest = jarFile.getManifest();
- String entryClass = manifest.getMainAttributes().getValue(ENTRY_NAME);
- if (StringUtils.isEmpty(entryClass)) {
- continue;
- }
-
- PluginClassLoader classLoader = new PluginClassLoader(jarFile);
- Class> klass = Class.forName(entryClass, false, classLoader);
- if (!Arrays.asList(klass.getInterfaces()).contains(PluginEntry.class)) {
- continue;
- }
-
- inst.appendToBootstrapClassLoaderSearch(jarFile);
-
- PluginEntry pluginEntry = (PluginEntry) Class.forName(entryClass).newInstance();
- pluginEntry.init(FilterConfig.getBySection(pluginEntry.getName()));
- Dispatcher.getInstance().addTransformers(pluginEntry.getTransformers());
-
- DebugInfo.output("Plugin loaded: {name=" + pluginEntry.getName() + ", version=" + pluginEntry.getVersion() + "}");
- } catch (Exception e) {
- DebugInfo.output("Load plugin failed: " + e.getMessage());
+ addPluginEntry(klass);
+ } catch (Throwable e) {
+ DebugInfo.output("Init plugin failed: " + e.getMessage());
}
}
}
+
+ private List> getAllPluginClasses(Instrumentation inst, File currentDirectory) {
+ List> classes = new ArrayList<>();
+ classes.add(DNSFilterPlugin.class);
+ classes.add(URLFilterPlugin.class);
+
+ do {
+ File pluginsDirectory = new File(currentDirectory, PLUGINS_DIR);
+ if (!pluginsDirectory.exists() || !pluginsDirectory.isDirectory()) {
+ break;
+ }
+
+ File[] pluginFiles = pluginsDirectory.listFiles((d, n) -> n.endsWith(".jar"));
+ if (null == pluginFiles) {
+ break;
+ }
+
+ for (File pluginFile : pluginFiles) {
+ try {
+ JarFile jarFile = new JarFile(pluginFile);
+ Manifest manifest = jarFile.getManifest();
+ String entryClass = manifest.getMainAttributes().getValue(ENTRY_NAME);
+ if (StringUtils.isEmpty(entryClass)) {
+ continue;
+ }
+
+ PluginClassLoader classLoader = new PluginClassLoader(jarFile);
+ Class> klass = Class.forName(entryClass, false, classLoader);
+ if (!Arrays.asList(klass.getInterfaces()).contains(PluginEntry.class)) {
+ continue;
+ }
+
+ inst.appendToBootstrapClassLoaderSearch(jarFile);
+ classes.add((Class extends PluginEntry>) Class.forName(entryClass));
+ } catch (Throwable e) {
+ DebugInfo.output("Load plugin failed: " + e.getMessage());
+ }
+ }
+ } while (false);
+
+ return classes;
+ }
+
+ private void addPluginEntry(Class extends PluginEntry> entryClass) throws Exception {
+ PluginEntry pluginEntry = entryClass.newInstance();
+
+ pluginEntry.init(FilterConfig.getBySection(pluginEntry.getName()));
+ Dispatcher.getInstance().addTransformers(pluginEntry.getTransformers());
+
+ DebugInfo.output("Plugin loaded: {name=" + pluginEntry.getName() + ", version=" + pluginEntry.getVersion() + ", author=" + pluginEntry.getAuthor() + "}");
+ }
}
diff --git a/src/main/java/io/zhile/research/ja/netfilter/filters/DNSFilter.java b/src/main/java/io/zhile/research/ja/netfilter/plugins/dns/DNSFilter.java
similarity index 70%
rename from src/main/java/io/zhile/research/ja/netfilter/filters/DNSFilter.java
rename to src/main/java/io/zhile/research/ja/netfilter/plugins/dns/DNSFilter.java
index dfe0baf..8596524 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/filters/DNSFilter.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugins/dns/DNSFilter.java
@@ -1,21 +1,25 @@
-package io.zhile.research.ja.netfilter.filters;
+package io.zhile.research.ja.netfilter.plugins.dns;
import io.zhile.research.ja.netfilter.commons.DebugInfo;
-import io.zhile.research.ja.netfilter.models.FilterConfig;
import io.zhile.research.ja.netfilter.models.FilterRule;
import java.io.IOException;
import java.net.InetAddress;
+import java.util.List;
public class DNSFilter {
- private static final String SECTION_NAME = "DNS";
+ private static List ruleList;
+
+ public static void setRules(List rules) {
+ ruleList = rules;
+ }
public static String testQuery(String host) throws IOException {
- if (null == host) {
+ if (null == host || null == ruleList) {
return null;
}
- for (FilterRule rule : FilterConfig.getBySection(SECTION_NAME)) {
+ for (FilterRule rule : ruleList) {
if (!rule.test(host)) {
continue;
}
@@ -28,11 +32,11 @@ public class DNSFilter {
}
public static Object testReachable(InetAddress n) throws IOException {
- if (null == n) {
+ if (null == n || null == ruleList) {
return null;
}
- for (FilterRule rule : FilterConfig.getBySection(SECTION_NAME)) {
+ for (FilterRule rule : ruleList) {
if (!rule.test(n.getHostName())) {
continue;
}
diff --git a/src/main/java/io/zhile/research/ja/netfilter/plugins/dns/DNSFilterPlugin.java b/src/main/java/io/zhile/research/ja/netfilter/plugins/dns/DNSFilterPlugin.java
new file mode 100644
index 0000000..6cf8113
--- /dev/null
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugins/dns/DNSFilterPlugin.java
@@ -0,0 +1,42 @@
+package io.zhile.research.ja.netfilter.plugins.dns;
+
+import io.zhile.research.ja.netfilter.models.FilterRule;
+import io.zhile.research.ja.netfilter.plugin.MyTransformer;
+import io.zhile.research.ja.netfilter.plugin.PluginEntry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DNSFilterPlugin implements PluginEntry {
+ private final List transformers = new ArrayList<>();
+
+ @Override
+ public void init(List filterRules) {
+ transformers.add(new InetAddressTransformer(filterRules));
+ }
+
+ @Override
+ public String getName() {
+ return "DNS";
+ }
+
+ @Override
+ public String getAuthor() {
+ return "neo";
+ }
+
+ @Override
+ public String getVersion() {
+ return "v1.0.0";
+ }
+
+ @Override
+ public String getDescription() {
+ return "ja-netfilter core: dns plugin";
+ }
+
+ @Override
+ public List getTransformers() {
+ return transformers;
+ }
+}
diff --git a/src/main/java/io/zhile/research/ja/netfilter/transformers/InetAddressTransformer.java b/src/main/java/io/zhile/research/ja/netfilter/plugins/dns/InetAddressTransformer.java
similarity index 76%
rename from src/main/java/io/zhile/research/ja/netfilter/transformers/InetAddressTransformer.java
rename to src/main/java/io/zhile/research/ja/netfilter/plugins/dns/InetAddressTransformer.java
index f95410b..920dfe7 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/transformers/InetAddressTransformer.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugins/dns/InetAddressTransformer.java
@@ -1,12 +1,22 @@
-package io.zhile.research.ja.netfilter.transformers;
+package io.zhile.research.ja.netfilter.plugins.dns;
+import io.zhile.research.ja.netfilter.models.FilterRule;
+import io.zhile.research.ja.netfilter.plugin.MyTransformer;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.tree.*;
+import java.util.List;
+
import static jdk.internal.org.objectweb.asm.Opcodes.*;
public class InetAddressTransformer implements MyTransformer {
+ private final List rules;
+
+ public InetAddressTransformer(List rules) {
+ this.rules = rules;
+ }
+
@Override
public String getHookClassName() {
return "java/net/InetAddress";
@@ -14,6 +24,8 @@ public class InetAddressTransformer implements MyTransformer {
@Override
public byte[] transform(String className, byte[] classBytes, int order) throws Exception {
+ DNSFilter.setRules(rules);
+
ClassReader reader = new ClassReader(classBytes);
ClassNode node = new ClassNode(ASM5);
reader.accept(node, 0);
@@ -22,7 +34,7 @@ public class InetAddressTransformer implements MyTransformer {
if ("getAllByName".equals(m.name) && "(Ljava/lang/String;Ljava/net/InetAddress;)[Ljava/net/InetAddress;".equals(m.desc)) {
InsnList list = new InsnList();
list.add(new VarInsnNode(ALOAD, 0));
- list.add(new MethodInsnNode(INVOKESTATIC, "io/zhile/research/ja/netfilter/filters/DNSFilter", "testQuery", "(Ljava/lang/String;)Ljava/lang/String;", false));
+ list.add(new MethodInsnNode(INVOKESTATIC, "io/zhile/research/ja/netfilter/plugins/dns/DNSFilter", "testQuery", "(Ljava/lang/String;)Ljava/lang/String;", false));
list.add(new InsnNode(POP));
m.instructions.insert(list);
@@ -32,7 +44,7 @@ public class InetAddressTransformer implements MyTransformer {
if ("isReachable".equals(m.name) && "(Ljava/net/NetworkInterface;II)Z".equals(m.desc)) {
InsnList list = new InsnList();
list.add(new VarInsnNode(ALOAD, 0));
- list.add(new MethodInsnNode(INVOKESTATIC, "io/zhile/research/ja/netfilter/filters/DNSFilter", "testReachable", "(Ljava/net/InetAddress;)Ljava/lang/Object;", false));
+ list.add(new MethodInsnNode(INVOKESTATIC, "io/zhile/research/ja/netfilter/plugins/dns/DNSFilter", "testReachable", "(Ljava/net/InetAddress;)Ljava/lang/Object;", false));
list.add(new VarInsnNode(ASTORE, 4));
list.add(new InsnNode(ACONST_NULL));
list.add(new VarInsnNode(ALOAD, 4));
diff --git a/src/main/java/io/zhile/research/ja/netfilter/transformers/HttpClientTransformer.java b/src/main/java/io/zhile/research/ja/netfilter/plugins/url/HttpClientTransformer.java
similarity index 73%
rename from src/main/java/io/zhile/research/ja/netfilter/transformers/HttpClientTransformer.java
rename to src/main/java/io/zhile/research/ja/netfilter/plugins/url/HttpClientTransformer.java
index 60c4303..4be940d 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/transformers/HttpClientTransformer.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugins/url/HttpClientTransformer.java
@@ -1,12 +1,22 @@
-package io.zhile.research.ja.netfilter.transformers;
+package io.zhile.research.ja.netfilter.plugins.url;
+import io.zhile.research.ja.netfilter.models.FilterRule;
+import io.zhile.research.ja.netfilter.plugin.MyTransformer;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.tree.*;
+import java.util.List;
+
import static jdk.internal.org.objectweb.asm.Opcodes.*;
public class HttpClientTransformer implements MyTransformer {
+ private final List rules;
+
+ public HttpClientTransformer(List rules) {
+ this.rules = rules;
+ }
+
@Override
public String getHookClassName() {
return "sun/net/www/http/HttpClient";
@@ -14,6 +24,8 @@ public class HttpClientTransformer implements MyTransformer {
@Override
public byte[] transform(String className, byte[] classBytes, int order) throws Exception {
+ URLFilter.setRules(rules);
+
ClassReader reader = new ClassReader(classBytes);
ClassNode node = new ClassNode(ASM5);
reader.accept(node, 0);
@@ -23,7 +35,7 @@ public class HttpClientTransformer implements MyTransformer {
InsnList list = new InsnList();
list.add(new VarInsnNode(ALOAD, 0));
list.add(new FieldInsnNode(GETFIELD, "sun/net/www/http/HttpClient", "url", "Ljava/net/URL;"));
- list.add(new MethodInsnNode(INVOKESTATIC, "io/zhile/research/ja/netfilter/filters/URLFilter", "testURL", "(Ljava/net/URL;)Ljava/net/URL;", false));
+ list.add(new MethodInsnNode(INVOKESTATIC, "io/zhile/research/ja/netfilter/plugins/url/URLFilter", "testURL", "(Ljava/net/URL;)Ljava/net/URL;", false));
list.add(new InsnNode(POP));
mn.instructions.insert(list);
diff --git a/src/main/java/io/zhile/research/ja/netfilter/filters/URLFilter.java b/src/main/java/io/zhile/research/ja/netfilter/plugins/url/URLFilter.java
similarity index 66%
rename from src/main/java/io/zhile/research/ja/netfilter/filters/URLFilter.java
rename to src/main/java/io/zhile/research/ja/netfilter/plugins/url/URLFilter.java
index 68ac5cd..37d53cc 100644
--- a/src/main/java/io/zhile/research/ja/netfilter/filters/URLFilter.java
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugins/url/URLFilter.java
@@ -1,22 +1,26 @@
-package io.zhile.research.ja.netfilter.filters;
+package io.zhile.research.ja.netfilter.plugins.url;
import io.zhile.research.ja.netfilter.commons.DebugInfo;
-import io.zhile.research.ja.netfilter.models.FilterConfig;
import io.zhile.research.ja.netfilter.models.FilterRule;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.URL;
+import java.util.List;
public class URLFilter {
- private static final String SECTION_NAME = "URL";
+ private static List ruleList;
+
+ public static void setRules(List rules) {
+ ruleList = rules;
+ }
public static URL testURL(URL url) throws IOException {
- if (null == url) {
+ if (null == url || null == ruleList) {
return null;
}
- for (FilterRule rule : FilterConfig.getBySection(SECTION_NAME)) {
+ for (FilterRule rule : ruleList) {
if (!rule.test(url.toString())) {
continue;
}
diff --git a/src/main/java/io/zhile/research/ja/netfilter/plugins/url/URLFilterPlugin.java b/src/main/java/io/zhile/research/ja/netfilter/plugins/url/URLFilterPlugin.java
new file mode 100644
index 0000000..faa143f
--- /dev/null
+++ b/src/main/java/io/zhile/research/ja/netfilter/plugins/url/URLFilterPlugin.java
@@ -0,0 +1,42 @@
+package io.zhile.research.ja.netfilter.plugins.url;
+
+import io.zhile.research.ja.netfilter.models.FilterRule;
+import io.zhile.research.ja.netfilter.plugin.MyTransformer;
+import io.zhile.research.ja.netfilter.plugin.PluginEntry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class URLFilterPlugin implements PluginEntry {
+ private final List transformers = new ArrayList<>();
+
+ @Override
+ public void init(List filterRules) {
+ transformers.add(new HttpClientTransformer(filterRules));
+ }
+
+ @Override
+ public String getName() {
+ return "URL";
+ }
+
+ @Override
+ public String getAuthor() {
+ return "neo";
+ }
+
+ @Override
+ public String getVersion() {
+ return "v1.0.0";
+ }
+
+ @Override
+ public String getDescription() {
+ return "ja-netfilter core: url plugin";
+ }
+
+ @Override
+ public List getTransformers() {
+ return transformers;
+ }
+}