Skip to content

Commit

Permalink
Configuring Stub Solver (#600)
Browse files Browse the repository at this point in the history
* testing new method

* implementing solver

* testing stub solver

* tested

* configured new solver

* fixing bug

* implementing ip version check

* setup the docs

* add ref

* english

* updating the docs

* [Gradle Release Plugin] - new version commit:  '3.32.1-snapshot'.
  • Loading branch information
mageddo authored Nov 7, 2024
1 parent 9ac46dd commit 461887c
Show file tree
Hide file tree
Showing 17 changed files with 263 additions and 17 deletions.
3 changes: 3 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 3.32.1
* Configuring Stub Solver. #545

## 3.32.0
* Implementing Stub Solver but not exposing. #545

Expand Down
48 changes: 48 additions & 0 deletions docs/content/2-features/stub-solver/_index.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: Stub Solver
---

You can use stub solver to transform IPs into hostnames without need to create a
configuration file as in Local DB Solver. Stub Solver was inspired in `nip.io` and `sslip.io`.

## Examples:

**Without a name:**

* `10.0.0.1.stub` => `10.0.0.1`
* `192-168-1-250.stub` => `192.168.1.250`
* `0a000803.stub` => `10.0.8.3`

**With a name:**

* `app.10.8.0.1.stub` => `10.8.0.1`
* `app-116-203-255-68.stub` => `116.203.255.68`
* `app-c0a801fc.stub` => `192.168.1.252`
* `customer1.app.10.0.0.1.stub` => `10.0.0.1`
* `customer2-app-127-0-0-1.stub` => `127.0.0.1`
* `customer3-app-7f000101.stub` => `127.0.1.1`
* `app.2a01-4f8-c17-b8f--2.stub` => `2a01:4f8:c17:b8f::2`

### Format Reference

```
${name}[.-]${ip_address}.stub
```

* `${name}` (optional): you can set a name to make it easier to recognize the IP
* `${ip_address}`: The ip address which the DNS will answer it can be in 4 formats
* dot notation: magic.127.0.0.1.stub
* dash notation: magic-127-0-0-1.stub
* hexadecimal notation: magic-7f000001.stub
* Ipv6 notation: magic.2a01-4f8-c17-b8f--2.stub

### Customize the domain name

<tbd>

## Refs

* [Stub Solver #545][1]


[1]: https://github.com/mageddo/dns-proxy-server/issues/545
11 changes: 7 additions & 4 deletions docs/content/3-configuration/_index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,17 @@ __Version 2__
"dockerSolverHostMachineFallbackActive": true,
"solverRemote" : {
"circuitBreaker" : {
"failureThreshold" : 3, // how many attempts before open the circuit?
"failureThresholdCapacity" : 10, // how many attempts store to the stack?
"successThreshold" : 5, // how many attempts before close the circuit?
"testDelay" : "PT20S" // how many time to wait before test the circuit again?, see https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#toString-- for format explanation
"failureThreshold" : 3,
"failureThresholdCapacity" : 10,
"successThreshold" : 5,
"testDelay" : "PT20S"
}
}
}
```

* [Solver remote circuit breaker configuration][3]

## Environment variable configuration

Boolean values
Expand All @@ -221,3 +223,4 @@ $ docker run defreitas/dns-proxy-server --help

[1]: {{%relref "2-features/auto-configuration-as-default-dns/_index.md" %}}
[2]: {{%relref "2-features/local-entries/_index.md" %}}
[3]: {{%relref "2-features/remote-solver-circuitbreaker/_index.en.md" %}}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=3.32.0-snapshot
version=3.32.1-snapshot
4 changes: 4 additions & 0 deletions src/main/java/com/mageddo/dns/Hostname.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ public String toString() {
public static Hostname of(String hostname) {
return new Hostname(hostname);
}

public boolean endsWith(String name) {
return this.value.endsWith(StringUtils.lowerCase(name));
}
}
10 changes: 9 additions & 1 deletion src/main/java/com/mageddo/dns/utils/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,11 @@ public static Message withResponseCode(Message res, int rRode) {
return res;
}

static Message withDefaultResponseHeaders(Message res) {
public static int getRCode(Message m){
return m.getRcode();
}

public static Message withDefaultResponseHeaders(Message res) {
final var header = res.getHeader();
header.setFlag(Flags.QR);
header.setFlag(Flags.RA);
Expand Down Expand Up @@ -305,4 +309,8 @@ public static boolean isSuccess(Message res) {
public static String findAnswerRawIP(Message res) {
return findFirstAnswerRecord(res).rdataToString();
}

public static boolean isNxDomain(Message m) {
return m.getRcode() == Rcode.NXDOMAIN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.mageddo.dnsproxyserver.solver.SolverDocker;
import com.mageddo.dnsproxyserver.solver.SolverLocalDB;
import com.mageddo.dnsproxyserver.solver.SolverSystem;
import com.mageddo.dnsproxyserver.solver.stub.SolverStub;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.ElementsIntoSet;
Expand All @@ -24,9 +25,9 @@ public interface ModuleSolver {
@Singleton
@ElementsIntoSet
static Set<Solver> solvers(
SolverSystem o1, SolverDocker o2, SolverLocalDB o3, SolverCachedRemote o4
SolverSystem o1, SolverDocker o2, SolverLocalDB o3, SolverCachedRemote o4, SolverStub o5
) {
return Set.of(o1, o2, o3, o4);
return Set.of(o1, o2, o3, o4, o5);
}

@Provides
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/solver/Response.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.NonNull;
import lombok.Value;
import org.xbill.DNS.Message;
import org.xbill.DNS.Rcode;

import java.time.Duration;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -50,6 +51,9 @@ public static Response of(Message message, Duration dpsTtl) {
}

public static Response nxDomain(Message message) {
if (!Messages.isNxDomain(message)) {
Messages.withResponseCode(message, Rcode.NXDOMAIN);
}
return of(message, DEFAULT_NXDOMAIN_TTL);
}

Expand All @@ -74,4 +78,8 @@ public Response withTTL(Duration ttl) {
.dpsTtl(ttl)
.build();
}

public int getRCode() {
return this.message.getRcode();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.mageddo.dnsproxyserver.solver;

import com.mageddo.commons.lang.Objects;
import com.mageddo.dns.utils.Messages;
import com.mageddo.net.IP;
import org.xbill.DNS.Message;

public class ResponseMapper {
public static Response toDefaultSuccessAnswer(Message query, IP ip, IP.Version version) {
return Response.of(
Messages.answer(query, Objects.mapOrNull(ip, IP::toText), version),
Messages.DEFAULT_TTL_DURATION
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class SolverProvider {

static final String[] solversOrder = {
"SolverSystem",
"SolverStub",
"SolverDocker",
SolverLocalDB.NAME,
SolverCachedRemote.NAME
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.mageddo.dnsproxyserver.solver;

import com.mageddo.commons.lang.Objects;
import com.mageddo.dns.utils.Messages;
import com.mageddo.dnsproxyserver.config.Config.Entry.Type;
import com.mageddo.dnsproxyserver.config.application.Configs;
import com.mageddo.dnsproxyserver.config.ConfigEntryTypes;
import com.mageddo.dns.utils.Messages;
import com.mageddo.dnsproxyserver.config.application.Configs;
import com.mageddo.dnsproxyserver.usecase.HostMachineService;
import com.mageddo.net.IP;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.xbill.DNS.Message;
Expand Down Expand Up @@ -36,10 +34,7 @@ public Response handle(Message query) {
if (hostname.isEqualTo(config.getHostMachineHostname())) { // fixme fazer case com hostname + search domain
final var ip = this.machineService.findHostMachineIP(questionType.toVersion());
log.debug("status=solvingHostMachineName, host={}, ip={}", hostname, ip);
return Response.of(
Messages.answer(query, Objects.mapOrNull(ip, IP::toText), questionType.toVersion()),
Messages.DEFAULT_TTL_DURATION
);
return ResponseMapper.toDefaultSuccessAnswer(query, ip, questionType.toVersion());
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
package com.mageddo.dnsproxyserver.solver.stub;

import com.mageddo.dns.Hostname;
import com.mageddo.dnsproxyserver.solver.stub.addressexpression.AddressExpressions;
import com.mageddo.dnsproxyserver.solver.stub.addressexpression.ParseException;
import com.mageddo.net.IP;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.Validate;

@Slf4j
public class HostnameIpExtractor {

public static IP safeExtract(Hostname hostname, String domain) {
try {
return extract(hostname, domain);
} catch (Exception e) {
log.info("status=failedToExtractIpFromHostname, hostname={}, msg={}", hostname, e.getMessage(), e);
return null;
}
}

public static IP extract(Hostname hostname, String domain) {
return extract(hostname.getCanonicalValue(), domain);
}

public static IP extract(String hostname, String domain) {

hostname = removeDomainFrom(hostname, domain);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,56 @@
package com.mageddo.dnsproxyserver.solver.stub;

import com.mageddo.dns.utils.Messages;
import com.mageddo.dnsproxyserver.config.Config;
import com.mageddo.dnsproxyserver.config.ConfigEntryTypes;
import com.mageddo.dnsproxyserver.solver.Response;
import com.mageddo.dnsproxyserver.solver.ResponseMapper;
import com.mageddo.dnsproxyserver.solver.Solver;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.xbill.DNS.Message;

import javax.inject.Inject;
import javax.inject.Singleton;

import static com.mageddo.dns.utils.Messages.findQuestionTypeCode;

/**
* Extract the address from the hostname then answer.
* Inspired at nip.io and sslip.io, see #545.
*/

@Slf4j
@Singleton
@AllArgsConstructor(onConstructor = @__({@Inject}))
public class SolverStub implements Solver {

public static final String DOMAIN_NAME = "stub";

@Override
public Response handle(Message query) {
return null;
final var questionType = Messages.findQuestionType(query);
if (ConfigEntryTypes.isNot(questionType, Config.Entry.Type.A, Config.Entry.Type.AAAA)) {
log.debug("status=unsupportedType, type={}, query={}", findQuestionTypeCode(query), Messages.simplePrint(query));
return null;
}

final var hostname = Messages.findQuestionHostname(query);
if (!hostname.endsWith(DOMAIN_NAME)) {
log.debug("status=hostnameDoesntMatchRequiredDomain, hostname={}", hostname);
return null;
}

final var foundIp = HostnameIpExtractor.safeExtract(hostname, DOMAIN_NAME);
if (foundIp == null) {
log.debug("status=notSolved, hostname={}", hostname);
return null;
}
if (!foundIp.isVersionEqualsTo(questionType.toVersion())) {
log.debug("status=incompatibleIpAndQueryType, hostname={}, questionType={}", hostname, questionType);
return Response.nxDomain(query);
}
log.debug("status=solved, host={}, ip={}", hostname, foundIp);
return ResponseMapper.toDefaultSuccessAnswer(query, foundIp, questionType.toVersion());
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/mageddo/net/IP.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ static List<IP> listOf(String ... ips) {

boolean notEqualTo(String ip);

default boolean isVersionEqualsTo(Version version){
return this.version().equals(version);
}

enum Version {

IPV4,
Expand Down
21 changes: 21 additions & 0 deletions src/test/java/com/mageddo/dns/HostnameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mageddo.dns;

import org.junit.jupiter.api.Test;
import testing.templates.HostnameTemplates;

import static org.junit.jupiter.api.Assertions.*;

class HostnameTest {

@Test
void mustEndsWith(){
final var hostname = Hostname.of(HostnameTemplates.NGINX_COM_BR);
assertTrue(hostname.endsWith(".com.br"));
}

@Test
void mustNotEndsWith(){
final var hostname = Hostname.of(HostnameTemplates.NGINX_COM_BR);
assertFalse(hostname.endsWith(".com"));
}
}
Loading

0 comments on commit 461887c

Please sign in to comment.