Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 5.9.0
* Answer all docker service replicas IPs, see #434.

## 5.8.4
* DNS over HTTPS, see #138
* Option to disable a specific container to be resolved from DPS, see #596.
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=5.8.4-snapshot
version=5.9.0-snapshot
38 changes: 28 additions & 10 deletions src/main/java/com/mageddo/dns/utils/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.List;
import java.util.Optional;

import com.mageddo.commons.Collections;
import com.mageddo.commons.lang.Objects;
import com.mageddo.dns.Hostname;
import com.mageddo.dnsproxyserver.config.Config.Entry;
Expand Down Expand Up @@ -123,12 +124,17 @@ public static Message aAnswer(Message query, String ip) {
}

public static Message aAnswer(Message query, String ip, long ttl) {
// FIXME EFS esse copy deveria ser feito por quem chama
// o mapper para evitar várias copias sem necessidade
final var res = withNoErrorResponse(copy(query));
if (StringUtils.isBlank(ip)) {
return res;
}
final var answer = new ARecord(res.getQuestion()
.getName(), DClass.IN, ttl, Ips.toAddress(ip)
final var answer = new ARecord(
findQuestionName(query),
DClass.IN,
ttl,
Ips.toAddress(ip)
);
res.addRecord(answer, Section.ANSWER);
return res;
Expand Down Expand Up @@ -251,12 +257,12 @@ public static Message quadAnswer(Message query, String ip) {
}

public static Message quadAnswer(final Message query, final String ip, final long ttl) {
final var res = withNoErrorResponse(query.clone());
final var res = withNoErrorResponse(copy(query));
if (StringUtils.isBlank(ip)) {
return res;
}
final var answer = new AAAARecord(res.getQuestion()
.getName(), DClass.IN, ttl, Ips.toAddress(ip)
final var answer = new AAAARecord(
findQuestionName(query), DClass.IN, ttl, Ips.toAddress(ip)
);
res.addRecord(answer, Section.ANSWER);
return res;
Expand All @@ -273,6 +279,17 @@ public static Message answer(Message query, String ip, Entry.Type type) {
return answer(query, ip, type, DEFAULT_TTL);
}

public static Message answer(Message query, List<String> ips, Entry.Type type, long ttl) {
if (Collections.isEmptyOrNull(ips)) {
return answer(query, (String) null, type, ttl);
}
Message res = query;
for (final var ip : ips) {
res = answer(res, ip, type, ttl);
}
return res;
}

public static Message answer(Message query, String ip, Entry.Type type, long ttl) {
Validate.notNull(type, "type must not be null, query=%s", toHostnameQuery(query));
return switch (type) {
Expand All @@ -287,10 +304,11 @@ static Message withNoErrorResponse(Message res) {
}

public static Message withResponseCode(Message res, int rRode) {
withDefaultResponseHeaders(res);
res.getHeader()
final var r = withDefaultResponseHeaders(res);
r
.getHeader()
.setRcode(rRode);
return res;
return r;
}

public static int getRCode(Message m) {
Expand Down Expand Up @@ -368,9 +386,9 @@ public static Message authoritativeAnswer(Message query, String ip, Entry.Type t
}

public static Message authoritativeAnswer(
Message query, String ip, Entry.Type type, long ttl
Message query, List<String> ips, Entry.Type type, long ttl
) {
return authoritative(answer(query, ip, type, ttl));
return authoritative(answer(query, ips, type, ttl));
}

public static boolean isAuthoritative(Message m) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.mageddo.dnsproxyserver.solver;

import java.time.Duration;
import java.util.List;

import com.mageddo.commons.Collections;
import com.mageddo.commons.lang.Objects;
import com.mageddo.dnsproxyserver.config.Config;
import com.mageddo.net.IP;

import lombok.Builder;
import lombok.Singular;
import lombok.Value;

import static java.util.Objects.requireNonNullElse;
Expand All @@ -17,14 +20,11 @@ public class AddressResolution {

boolean hostnameMatched;

IP ip;
@Singular
List<IP> ips;

Duration ttl;

public String getIpText() {
return this.ip != null ? this.ip.toText() : null;
}

public Duration getTTL(Duration def) {
return requireNonNullElse(this.ttl, def);
}
Expand All @@ -38,19 +38,17 @@ public boolean isHostNameNotMatched() {
}

public boolean hasNotIP() {
return this.ip == null;
return !this.hasIp();
}

public boolean hasIp() {
return this.ip != null;
return Collections.isNotEmpty(this.ips);
}

public String getIp(Config.Entry.Type type) {
@SuppressWarnings("unchecked")
public List<String> getIps(Config.Entry.Type type) {
final var version = type.toVersion();
if (this.hasNotIP() || version == null || this.ip.versionIs(version)) {
return this.getIpText();
}
return null;
return IpMapper.toText(this.ips, version);
}

public static AddressResolution matched(IP ip) {
Expand All @@ -62,6 +60,12 @@ public static AddressResolution matched(IP ip, Integer ttl) {
}

public static AddressResolution matched(IP ip, Duration ttl) {
if (ip == null) {
return builder()
.hostnameMatched(true)
.ttl(ttl)
.build();
}
return builder()
.hostnameMatched(true)
.ip(ip)
Expand All @@ -75,4 +79,7 @@ public static AddressResolution notMatched() {
.build();
}

public String firstAsText() {
return IpMapper.toText(Collections.first(this.ips));
}
}
32 changes: 32 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/solver/IpMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.mageddo.dnsproxyserver.solver;

import java.util.List;
import java.util.Objects;

import com.mageddo.commons.Collections;
import com.mageddo.net.IP;

import org.apache.commons.lang3.ObjectUtils;

public class IpMapper {

public static List<String> toText(List<IP> ips) {
return Collections.mapNonNulls(ips, IpMapper::toText);
}

public static String toText(IP ip) {
return ip != null ? ip.toText() : null;
}

public static List<String> toText(List<IP> ips, IP.Version version) {
if (version == null) {
return IpMapper.toText(ips);
}
return ObjectUtils.firstNonNull(ips, Collections.<IP>emptyList())
.stream()
.filter(Objects::nonNull)
.filter(ip -> ip.versionIs(version))
.map(IpMapper::toText)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public Response mapDynamicFromResolution(
return HostnameEvaluator.eval(
askedHost,
version,
hostnameQuery -> map(query, finder, hostnameQuery, type)
hostnameQuery -> this.map(query, finder, hostnameQuery, type)
);
}

Expand Down Expand Up @@ -89,7 +89,7 @@ public Response map(Message query, AddressResolution res, Entry.Type type) {
final var ttl = res.getTTL(this.defaultTTL);
final var msg = Messages.authoritativeAnswer(
query,
res.getIp(type),
res.getIps(type),
type,
ttl.toSeconds()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public Response handle(Message query) {
return null;
}

return this.handler.mapDynamicFromResolution(query,
this.containerSolvingService::findBestMatch
return this.handler.mapDynamicFromResolution(
query, this.containerSolvingService::findBestMatch
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mageddo.dnsproxyserver.solver.docker.application;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
Expand All @@ -10,9 +11,9 @@
import javax.inject.Singleton;

import com.mageddo.dnsproxyserver.config.application.Configs;
import com.mageddo.dnsproxyserver.solver.AddressResolution;
import com.mageddo.dnsproxyserver.solver.HostnameQuery;
import com.mageddo.dnsproxyserver.solver.docker.Container;
import com.mageddo.dnsproxyserver.solver.AddressResolution;
import com.mageddo.dnsproxyserver.solver.docker.Network;
import com.mageddo.dnsproxyserver.solver.docker.dataprovider.ContainerDAO;
import com.mageddo.dnsproxyserver.solver.docker.dataprovider.DockerDAO;
Expand Down Expand Up @@ -40,24 +41,28 @@ public class ContainerSolvingService {
public AddressResolution findBestMatch(HostnameQuery query) {
final var stopWatch = StopWatch.createStarted();
final var matchedContainers = this.containerDAO.findActiveContainersMatching(query);
final var foundIp = matchedContainers
.stream()
.map(it -> this.findBestIpMatch(it, query.getVersion()))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
final var foundIps = this.mapToIps(matchedContainers, query);
final var hostnameMatched = !matchedContainers.isEmpty();
log.trace(
"status=findDone, query={}, found={}, hostnameMatched={}, time={}",
query, foundIp, hostnameMatched, stopWatch.getTime()
"status=done, query={}, found={}, hostnameMatched={}, time={}",
query, foundIps, hostnameMatched, stopWatch.getTime()
);
return AddressResolution
.builder()
.hostnameMatched(hostnameMatched)
.ip(IP.of(foundIp))
.ips(foundIps)
.build();
}

List<IP> mapToIps(List<Container> containers, HostnameQuery query) {
return containers
.stream()
.map(it -> this.findBestIpMatch(it, query.getVersion()))
.filter(Objects::nonNull)
.map(IP::of)
.toList();
}

public String findBestIpMatch(Container c) {
return this.findBestIpMatch(c, IP.Version.IPV4);
}
Expand Down
48 changes: 48 additions & 0 deletions src/test/java/com/mageddo/dnsproxyserver/solver/IpMapperTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.mageddo.dnsproxyserver.solver;

import java.util.List;

import com.mageddo.net.IP;

import org.junit.jupiter.api.Test;

import testing.templates.IpTemplates;

import static org.assertj.core.api.Assertions.assertThat;

class IpMapperTest {

@Test
void mustReturnAllVersionsAreMixed() {

final var mixed = List.of(IpTemplates.local(), IpTemplates.localIpv6());

final var ips = IpMapper.toText(mixed);

assertThat(ips)
.hasSize(2)
.containsExactly(
"10.10.0.1", "2001:db8:1:0:0:0:0:2"
);

}
@Test
void musGetOnlyIpv6() {

final var mixed = List.of(
IpTemplates.local(),
IpTemplates.localIpv6(),
IpTemplates.localIpv6_3()
);

final var ips = IpMapper.toText(mixed, IP.Version.IPV6);

assertThat(ips)
.hasSize(2)
.containsExactly(
"2001:db8:1:0:0:0:0:2",
"2001:db8:1:0:0:0:0:3"
);

}
}
Loading