Skip to content

Commit a06b86e

Browse files
committed
Use dnsjava/dnsjava as DNS Provider, also add it's experiment in lab, an dependency of #834
1 parent 38c5b0b commit a06b86e

File tree

10 files changed

+154
-14
lines changed

10 files changed

+154
-14
lines changed

pom.xml

+5
Original file line numberDiff line numberDiff line change
@@ -510,5 +510,10 @@
510510
<artifactId>java-multiaddr</artifactId>
511511
<version>v1.4.12</version>
512512
</dependency>
513+
<dependency>
514+
<groupId>dnsjava</groupId>
515+
<artifactId>dnsjava</artifactId>
516+
<version>3.6.2</version>
517+
</dependency>
513518
</dependencies>
514519
</project>

src/main/java/com/ghostchu/peerbanhelper/PeerBanHelperServer.java

+28-5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.ghostchu.peerbanhelper.invoker.impl.IPFilterInvoker;
2424
import com.ghostchu.peerbanhelper.ipdb.IPDB;
2525
import com.ghostchu.peerbanhelper.ipdb.IPGeoData;
26+
import com.ghostchu.peerbanhelper.lab.Experiments;
2627
import com.ghostchu.peerbanhelper.lab.Laboratory;
2728
import com.ghostchu.peerbanhelper.metric.BasicMetrics;
2829
import com.ghostchu.peerbanhelper.module.*;
@@ -34,6 +35,7 @@
3435
import com.ghostchu.peerbanhelper.text.TranslationComponent;
3536
import com.ghostchu.peerbanhelper.torrent.Torrent;
3637
import com.ghostchu.peerbanhelper.util.*;
38+
import com.ghostchu.peerbanhelper.util.dns.DNSLookup;
3739
import com.ghostchu.peerbanhelper.util.encrypt.RSAUtils;
3840
import com.ghostchu.peerbanhelper.util.json.JsonUtil;
3941
import com.ghostchu.peerbanhelper.util.paging.Pageable;
@@ -59,6 +61,7 @@
5961
import inet.ipaddr.format.util.DualIPv4v6Tries;
6062
import io.javalin.util.JavalinBindException;
6163
import lombok.Getter;
64+
import lombok.SneakyThrows;
6265
import lombok.extern.slf4j.Slf4j;
6366
import org.apache.commons.lang3.StringUtils;
6467
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
@@ -139,6 +142,8 @@ public class PeerBanHelperServer implements Reloadable {
139142
private BanListDao banListDao;
140143
@Autowired
141144
private Laboratory laboratory;
145+
@Autowired
146+
private DNSLookup dnsLookup;
142147
// @Autowired
143148
// private IPFSBanListShare share;
144149

@@ -197,7 +202,15 @@ public void start() throws SQLException {
197202
Main.getReloadManager().register(this);
198203
Main.getEventBus().post(new PBHServerStartedEvent(this));
199204
sendSnapshotAlert();
205+
runTestCode();
206+
}
200207

208+
@SneakyThrows
209+
private void runTestCode() {
210+
if (!"LiveDebug".equalsIgnoreCase(System.getProperty("pbh.release"))) {
211+
return;
212+
}
213+
// run some junky test code here
201214
}
202215

203216
private void setupScriptEngine() {
@@ -675,7 +688,7 @@ public void updateDownloader(@NotNull Downloader downloader, boolean updateBanLi
675688
try {
676689
var loginResult = downloader.login();
677690
if (!loginResult.success()) {
678-
if(loginResult.getStatus() != DownloaderLoginResult.Status.PAUSED) {
691+
if (loginResult.getStatus() != DownloaderLoginResult.Status.PAUSED) {
679692
log.error(tlUI(Lang.ERR_CLIENT_LOGIN_FAILURE_SKIP, downloader.getName(), downloader.getEndpoint(), tlUI(loginResult.getMessage())));
680693
downloader.setLastStatus(DownloaderLastStatus.ERROR, loginResult.getMessage());
681694
}
@@ -769,7 +782,7 @@ public Map<Torrent, List<Peer>> collectPeers(Downloader downloader) {
769782
Map<Torrent, List<Peer>> peers = new ConcurrentHashMap<>();
770783
var loginResult = downloader.login();
771784
if (!loginResult.success()) {
772-
if(loginResult.getStatus() != DownloaderLoginResult.Status.PAUSED){
785+
if (loginResult.getStatus() != DownloaderLoginResult.Status.PAUSED) {
773786
log.error(tlUI(Lang.ERR_CLIENT_LOGIN_FAILURE_SKIP, downloader.getName(), downloader.getEndpoint(), tlUI(loginResult.getMessage())));
774787
downloader.setLastStatus(DownloaderLastStatus.ERROR, loginResult.getMessage());
775788
if (loginResult.getStatus() == DownloaderLoginResult.Status.MISSING_COMPONENTS || loginResult.getStatus() == DownloaderLoginResult.Status.REQUIRE_TAKE_ACTIONS) {
@@ -920,9 +933,19 @@ private void banPeer(@NotNull Collection<PeerAddress> compareWith, @NotNull BanM
920933
banMetadata.setReverseLookup("N/A");
921934
if (Main.getMainConfig().getBoolean("lookup.dns-reverse-lookup")) {
922935
executor.submit(() -> {
923-
String hostName = peer.getPeerAddress().getAddress().toInetAddress().getHostName();
924-
if (!peer.getPeerAddress().getIp().equals(hostName)) {
925-
banMetadata.setReverseLookup(peer.getPeerAddress().getAddress().toInetAddress().getHostName());
936+
if (laboratory.isExperimentActivated(Experiments.DNSJAVA.getExperiment())) {
937+
dnsLookup.ptr(peer.getPeerAddress().getAddress().toReverseDNSLookupString()).thenAccept(hostName -> {
938+
if (hostName.isPresent()) {
939+
if (!peer.getPeerAddress().getIp().equals(hostName.get())) {
940+
banMetadata.setReverseLookup(hostName.get());
941+
}
942+
}
943+
});
944+
} else {
945+
String hostName = peer.getPeerAddress().getAddress().toInetAddress().getHostName();
946+
if (!peer.getPeerAddress().getIp().equals(hostName)) {
947+
banMetadata.setReverseLookup(peer.getPeerAddress().getAddress().toInetAddress().getHostName());
948+
}
926949
}
927950
});
928951
}

src/main/java/com/ghostchu/peerbanhelper/lab/Experiments.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import java.util.List;
77

88
public enum Experiments {
9-
IPFS(new Experiment("ipfs", List.of(0), new TranslationComponent(Lang.LAB_EXPERIMENT_IPFS_TITLE), new TranslationComponent(Lang.LAB_EXPERIMENT_IPFS_DESCRIPTION)));
9+
IPFS(new Experiment("ipfs", List.of(0), new TranslationComponent(Lang.LAB_EXPERIMENT_IPFS_TITLE), new TranslationComponent(Lang.LAB_EXPERIMENT_IPFS_DESCRIPTION))),
10+
DNSJAVA(new Experiment("dnsjava", List.of(0, 1, 2), new TranslationComponent(Lang.LAB_EXPERIMENT_DNSJAVA_TITLE), new TranslationComponent(Lang.LAB_EXPERIMENT_DNSJAVA_DESCRIPTION)));
1011

1112
private final Experiment experiment;
1213

src/main/java/com/ghostchu/peerbanhelper/lab/Laboratory.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public Laboratory() throws IOException {
3737
}
3838

3939
public boolean isExperimentActivated(Experiment experiment) {
40-
if(!isEnabled()){
40+
if (!isEnabled()) {
4141
return false;
4242
}
4343
var value = labConfig.getString(experiment.getId());
@@ -57,16 +57,16 @@ public boolean isExperimentActivated(Experiment experiment) {
5757
}
5858
}
5959

60-
public void setExperimentActivated(String id, Boolean activated) throws IllegalArgumentException{
60+
public void setExperimentActivated(String id, Boolean activated) throws IllegalArgumentException {
6161
for (Experiments value : Experiments.values()) {
62-
if(!value.getExperiment().getId().equals(id)){
62+
if (!value.getExperiment().getId().equals(id)) {
6363
continue;
6464
}
6565
labConfig.set(value.getExperiment().getId(), activated == null ? "default" : activated);
6666
saveLabConfig();
6767
return;
6868
}
69-
throw new IllegalArgumentException("Invalid experiment id: "+id+", it's not exists in Experiments registry");
69+
throw new IllegalArgumentException("Invalid experiment id: " + id + ", it's not exists in Experiments registry");
7070
}
7171

7272
private void saveLabConfig() {

src/main/java/com/ghostchu/peerbanhelper/text/Lang.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ public enum Lang {
467467
FREE_LICENSE_DESCRIPTION,
468468
FREE_LICENSE_SOURCE,
469469
FREE_LICENSE_LICENSE_TO,
470-
FREE_LICENSE_RENEW_STILL_ACTIVE, PBH_PLUS_LICENSE_UPDATED, DOWNLOADER_QB_DISABLE_SAME_IP_MULTI_CONNECTION_FAILED, DOWNLOADER_PAUSED;
470+
FREE_LICENSE_RENEW_STILL_ACTIVE, PBH_PLUS_LICENSE_UPDATED, DOWNLOADER_QB_DISABLE_SAME_IP_MULTI_CONNECTION_FAILED, DOWNLOADER_PAUSED, LAB_EXPERIMENT_DNSJAVA_TITLE, LAB_EXPERIMENT_DNSJAVA_DESCRIPTION;
471471

472472
public String getKey() {
473473
return name();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.ghostchu.peerbanhelper.util.dns;
2+
3+
import com.ghostchu.peerbanhelper.Main;
4+
import com.ghostchu.simplereloadlib.ReloadResult;
5+
import com.ghostchu.simplereloadlib.Reloadable;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.springframework.stereotype.Component;
8+
import org.xbill.DNS.Record;
9+
import org.xbill.DNS.*;
10+
import oshi.SystemInfo;
11+
12+
import java.net.UnknownHostException;
13+
import java.time.Duration;
14+
import java.time.temporal.ChronoUnit;
15+
import java.util.ArrayList;
16+
import java.util.Arrays;
17+
import java.util.List;
18+
import java.util.Optional;
19+
import java.util.concurrent.CompletableFuture;
20+
21+
@Slf4j
22+
@Component
23+
public class DNSLookup implements Reloadable {
24+
private volatile ExtendedResolver resolver = new ExtendedResolver();
25+
26+
public DNSLookup() {
27+
reloadConfig();
28+
Main.getReloadManager().register(this);
29+
}
30+
31+
@Override
32+
public ReloadResult reloadModule() throws Exception {
33+
reloadConfig();
34+
return Reloadable.super.reloadModule();
35+
}
36+
37+
private void reloadConfig() {
38+
// get system dns via oshi
39+
SystemInfo systemInfo = new SystemInfo();
40+
var dnsServers = systemInfo.getOperatingSystem().getNetworkParams().getDnsServers();
41+
List<String> dns = Main.getMainConfig().getStringList("resolvers.servers");
42+
if (Main.getMainConfig().getBoolean("resolvers.use-system",true)) {
43+
dns.addAll(Arrays.asList(dnsServers));
44+
}
45+
applyDnsServers(dns);
46+
}
47+
48+
private void applyDnsServers(List<String> servers) {
49+
List<Resolver> resolvers = new ArrayList<>();
50+
for (String dns : servers) {
51+
if (dns.startsWith("http")) {
52+
resolvers.add(new DohResolver(dns));
53+
log.info("Added DoH resolver: {}", dns);
54+
} else {
55+
try {
56+
resolvers.add(new SimpleResolver(dns));
57+
log.info("Added resolver: {}", dns);
58+
} catch (UnknownHostException e) {
59+
log.warn("Failed to add resolver: {}", dns, e);
60+
}
61+
}
62+
}
63+
var replace = new ExtendedResolver(resolvers.toArray(new Resolver[0]));
64+
replace.setLoadBalance(true);
65+
replace.setTimeout(Duration.of(3, ChronoUnit.SECONDS));
66+
resolver = replace;
67+
}
68+
69+
public CompletableFuture<Optional<String>> ptr(String query) {
70+
return CompletableFuture.supplyAsync(() -> {
71+
try {
72+
Lookup lookup = new Lookup(query, Type.PTR);
73+
lookup.setResolver(resolver);
74+
lookup.run();
75+
if (lookup.getResult() == Lookup.SUCCESSFUL) {
76+
Record[] records = lookup.getAnswers();
77+
for (Record record : records) {
78+
if (record instanceof PTRRecord ptr) {
79+
return Optional.of(ptr.getTarget().toString());
80+
}
81+
}
82+
return Optional.empty();
83+
}
84+
return Optional.empty();
85+
} catch (TextParseException ignored) {
86+
return Optional.empty();
87+
}
88+
});
89+
}
90+
91+
}

src/main/resources/config.yml

+14
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,17 @@ decentralized:
173173
# 发布当前封禁列表到 IPFS 以允许它人订阅您的封禁列表内容,时间单位:毫秒,设置为 -1 以禁用
174174
# Publish current banlist to IPFS to allow others subscribe your banlist, time unit: milliseconds, set to -1 to disable
175175
publish-banlist: 3600000
176+
177+
# 自定义 DNS 解析器,暂不支持 DoH/DoT/DoQ
178+
# 留空则使用系统 DNS
179+
# 部分 DNS 存在速率限制,建议使用与系统 DNS 不同的 DNS,以避免影响正常上网解析
180+
# 要使此配置生效,需要启用 DNSJava 实验
181+
# Custom DNS resolver, DoT/DoQ are not supported yet
182+
# Leave it empty to use system DNS
183+
# Some DNS have rate limit, it's recommended to use different DNS with system DNS to avoid affect normal internet access
184+
# To make this config take effect, you need enable DNSJava experiment
185+
resolvers:
186+
# 使用系统 DNS - Use system DNS
187+
use-system: true
188+
# 自定义 DNS 服务器列表 - Custom DNS server list
189+
servers: []

src/main/resources/lang/en_us/messages.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -535,4 +535,6 @@ FREE_LICENSE_RENEW_STILL_ACTIVE: "The current license is still active and does n
535535
FREE_LICENSE_SOURCE: "Locally generated free license."
536536
FREE_LICENSE_LICENSE_TO: "{} for personal use."
537537
FREE_LICENSE_DESCRIPTION: "Local generated renewable free license, for personal use only."
538-
DOWNLOADER_PAUSED: Downloader paused
538+
DOWNLOADER_PAUSED: Downloader paused
539+
LAB_EXPERIMENT_DNSJAVA_TITLE: "DNSJava DNS"
540+
LAB_EXPERIMENT_DNSJAVA_DESCRIPTION: "Use [dnsjava/dnsjava](https://github.com/dnsjava/dnsjava) to replace the default JDK DNS resolver in some modules, providing more reliable hostname and reverse DNS lookup capabilities, and supporting custom DNS servers and load balancing. DNSJava only works for certain functions (such as reverse DNS lookup), while other functions will continue to use JDK DNS. \nAfter enabling this experiment, you can configure the DNS server addresses for DNSJava in the configuration file."

src/main/resources/lang/messages_fallback.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -535,4 +535,6 @@ FREE_LICENSE_SOURCE: "本地生成的免费许可证"
535535
FREE_LICENSE_LICENSE_TO: "{} 用于个人用途"
536536
FREE_LICENSE_DESCRIPTION: "本地生成的循环免费许可证,仅用于个人用途"
537537
DOWNLOADER_QB_DISABLE_SAME_IP_MULTI_CONNECTION_FAILED: "禁用 {} ({}) 的高级设置 “允许来自不同 IP 地址的多重连接” 失败:{} - {}!此功能必须关闭,否则将导致 PCB 封禁误判。"
538-
DOWNLOADER_PAUSED: "下载器已暂停"
538+
DOWNLOADER_PAUSED: "下载器已暂停"
539+
LAB_EXPERIMENT_DNSJAVA_TITLE: "DNSJava DNS 解析"
540+
LAB_EXPERIMENT_DNSJAVA_DESCRIPTION: "在部分功能模块中使用 [dnsjava/dnsjava](https://github.com/dnsjava/dnsjava) 替代 JDK 默认的 DNS 解析器,以提供更可靠的主机名和反向 DNS 查询能力,并支持自定义 DNS 服务器和负载均衡的能力。DNSJava 仅在部分功能上工作(如 DNS 反查),其它功能将继续使用 JDK DNS。 \n启用此实验后,您可以在配置文件中配置 DNSJava 的 DNS 服务器地址。"

src/main/resources/lang/zh_cn/messages.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -532,4 +532,6 @@ FREE_LICENSE_RENEW_STILL_ACTIVE: "当前许可证仍在有效期内,无需重
532532
FREE_LICENSE_SOURCE: "本地生成的免费许可证"
533533
FREE_LICENSE_LICENSE_TO: "{} 用于个人用途"
534534
FREE_LICENSE_DESCRIPTION: "本地生成的循环免费许可证,仅用于个人用途"
535-
DOWNLOADER_PAUSED: "下载器已暂停"
535+
DOWNLOADER_PAUSED: "下载器已暂停"
536+
LAB_EXPERIMENT_DNSJAVA_TITLE: "DNSJava DNS 解析"
537+
LAB_EXPERIMENT_DNSJAVA_DESCRIPTION: "在部分功能模块中使用 [dnsjava/dnsjava](https://github.com/dnsjava/dnsjava) 替代 JDK 默认的 DNS 解析器,以提供更可靠的主机名和反向 DNS 查询能力,并支持自定义 DNS 服务器和负载均衡的能力。DNSJava 仅在部分功能上工作(如 DNS 反查),其它功能将继续使用 JDK DNS。 \n启用此实验后,您可以在配置文件中配置 DNSJava 的 DNS 服务器地址。"

0 commit comments

Comments
 (0)