Skip to content

Commit bfbc859

Browse files
authored
DNS SERVER: Fixing IPV6 query answers which could fail in some cases by UDP interface issues (#666)
1 parent 90b83c0 commit bfbc859

File tree

11 files changed

+105
-18
lines changed

11 files changed

+105
-18
lines changed

RELEASE-NOTES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
## 5.5.0
1+
## 5.5.1
22
* Releasing JRE Docker Image Version
33
* Enabling DPS to run on any JRE 21+
4+
* Fixing IPV6 query answers which could fail in some cases by UDP interface issues
45

56
## 5.3.0
67
* Docker Solver: Specify Preferred Networks to use when solving container IP #662

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=5.5.0-snapshot
1+
version=5.5.1-snapshot

src/main/java/com/mageddo/dnsproxyserver/solver/stub/SolverStub.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public Response handle(Message query) {
5151
log.debug("status=notSolved, hostname={}", hostname);
5252
return null;
5353
}
54-
if (!foundIp.isVersionEqualsTo(questionType.toVersion())) {
54+
if (!foundIp.versionIs(questionType.toVersion())) {
5555
log.debug("status=incompatibleIpAndQueryType, hostname={}, questionType={}", hostname,
5656
questionType
5757
);

src/main/java/com/mageddo/dnsproxyserver/utils/InetAddresses.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33
import java.net.InetSocketAddress;
44

5+
import com.mageddo.net.IP;
56
import com.mageddo.net.IpAddr;
67

78
public class InetAddresses {
89

10+
public static InetSocketAddress toSocketAddress(IP ip, int port) {
11+
return new InetSocketAddress(Ips.toAddress(ip), port);
12+
}
13+
914
public static InetSocketAddress toSocketAddress(String ip, int port) {
1015
return new InetSocketAddress(Ips.toAddress(ip), port);
1116
}

src/main/java/com/mageddo/dnsproxyserver/utils/Ips.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ public static InetSocketAddress getAnyLocalAddress(int port) {
7575
return new InetSocketAddress(getAnyLocalAddress(), port);
7676
}
7777

78+
public static InetSocketAddress getAnyLocalIpv6Address(int port) {
79+
return new InetSocketAddress(getAnyLocalIpv6Address(), port);
80+
}
81+
82+
public static InetAddress getAnyLocalIpv6Address() {
83+
try {
84+
return InetAddress.getByAddress(new byte[16]);
85+
} catch (UnknownHostException e) {
86+
return null;
87+
}
88+
}
89+
7890
public static boolean isIpv6(String v) {
7991
return StringUtils.trimToEmpty(v)
8092
.contains(":");
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.mageddo.dnsserver;
2+
3+
import java.util.List;
4+
5+
import com.mageddo.commons.Collections;
6+
import com.mageddo.net.IP;
7+
import com.mageddo.net.Networks;
8+
9+
import lombok.extern.slf4j.Slf4j;
10+
11+
@Slf4j
12+
public class Addresses {
13+
14+
public static List<IP> findBindAddresses(IP address) {
15+
try {
16+
return mustFindBindAddresses(address);
17+
} catch (Exception e) {
18+
log.warn(
19+
"status=couldNotFindBestBindAddresses, action=pleaseReportThat, using={}, msg={}",
20+
address, e.getMessage(), e
21+
);
22+
return Collections.singletonList(address);
23+
}
24+
}
25+
26+
private static List<IP> mustFindBindAddresses(IP address) {
27+
if (!address.isAnyLocal()) {
28+
return Collections.singletonList(address);
29+
}
30+
if (address.versionIs(IP.Version.IPV6)) {
31+
return Networks.findMachineIps();
32+
}
33+
return Collections.filter(
34+
Networks.findMachineIps(),
35+
ip -> ip.versionIs(address.version())
36+
);
37+
}
38+
}

src/main/java/com/mageddo/dnsserver/UDPServer.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.mageddo.dnsserver;
22

3+
import java.io.IOException;
34
import java.net.DatagramPacket;
45
import java.net.DatagramSocket;
56
import java.net.SocketAddress;
@@ -36,21 +37,25 @@ public void start() {
3637

3738
private void start0() {
3839
try {
39-
this.server = new DatagramSocket(this.address);
40-
while (!server.isClosed()) {
40+
this.server = this.createSocket();
41+
while (!this.server.isClosed()) {
4142

4243
final var datagram = new DatagramPacket(new byte[BUFFER_SIZE], 0, BUFFER_SIZE);
43-
server.receive(datagram);
44+
this.server.receive(datagram);
4445

45-
this.pool.submit(() -> this.handle(server, datagram));
46+
this.pool.submit(() -> this.handle(this.server, datagram));
4647

4748
}
4849
} catch (Exception e) {
49-
log.error("status=dnsServerStartFailed, address={}, msg={}", address, e.getMessage(), e);
50+
log.error("status=dnsServerStartFailed, address={}, msg={}", this.address, e.getMessage(), e);
5051
throw new RuntimeException(e);
5152
}
5253
}
5354

55+
private DatagramSocket createSocket() throws IOException {
56+
return new DatagramSocket(this.address);
57+
}
58+
5459
void handle(DatagramSocket server, DatagramPacket datagram) {
5560
try {
5661
final var query = new Message(datagram.getData());

src/main/java/com/mageddo/dnsserver/UDPServerPool.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package com.mageddo.dnsserver;
22

3+
import java.net.InetSocketAddress;
34
import java.net.SocketAddress;
45
import java.util.ArrayList;
5-
import java.util.Collections;
66
import java.util.List;
77
import java.util.stream.Collectors;
88

99
import javax.inject.Inject;
1010
import javax.inject.Singleton;
1111

12+
import com.mageddo.commons.Collections;
13+
import com.mageddo.dnsproxyserver.utils.InetAddresses;
1214
import com.mageddo.dnsproxyserver.utils.Ips;
15+
import com.mageddo.net.IP;
1316

1417
import lombok.RequiredArgsConstructor;
1518
import lombok.extern.slf4j.Slf4j;
@@ -23,15 +26,31 @@ public class UDPServerPool {
2326
private List<UDPServer> servers = new ArrayList<>();
2427

2528
public void start(int port) {
26-
this.servers = Collections.singletonList(
27-
new UDPServer(Ips.getAnyLocalAddress(port), this.requestHandler));
29+
final var addresses = this.buildAddressesToBind(port);
30+
this.servers = Collections.map(
31+
addresses,
32+
address -> new UDPServer(address, this.requestHandler)
33+
);
2834
this.servers.forEach(UDPServer::start);
29-
final var addresses = this.servers
30-
.stream()
31-
.map(UDPServer::getAddress)
35+
log.info("Starting UDP server, addresses={}", this.toString(addresses));
36+
}
37+
38+
private List<InetSocketAddress> buildAddressesToBind(int port) {
39+
final var bindIp = Ips.from(Ips.getAnyLocalIpv6Address());
40+
return this.buildAddressesToBind(bindIp, port);
41+
}
42+
43+
private List<InetSocketAddress> buildAddressesToBind(IP ip, int port) {
44+
return Collections.map(
45+
Addresses.findBindAddresses(ip),
46+
it -> InetAddresses.toSocketAddress(it, port)
47+
);
48+
}
49+
50+
private String toString(List<InetSocketAddress> addresses) {
51+
return addresses.stream()
3252
.map(SocketAddress::toString)
3353
.collect(Collectors.joining(", "));
34-
log.info("Starting UDP server, addresses={}", addresses);
3554
}
3655

3756
public void stop() {

src/main/java/com/mageddo/net/IP.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ static List<IP> listOf(String... ips) {
3535

3636
boolean isLoopback();
3737

38+
boolean isAnyLocal();
39+
3840
boolean notEqualTo(String ip);
3941

40-
default boolean isVersionEqualsTo(Version version) {
42+
default boolean versionIs(Version version) {
4143
return this.version()
4244
.equals(version);
4345
}

src/main/java/com/mageddo/net/IpImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ public boolean isLoopback() {
8484
return this.ip.isLoopbackAddress();
8585
}
8686

87+
@Override
88+
public boolean isAnyLocal() {
89+
return this.ip.isAnyLocalAddress();
90+
}
91+
8792
@Override
8893
public boolean notEqualTo(String ip) {
8994
return !Objects.equals(this, IP.of(ip));

0 commit comments

Comments
 (0)