Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPS 3 - Features #268

Merged
merged 28 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
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
6 changes: 1 addition & 5 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@
root = true

# Unix-style newlines with a newline ending every file
[*.go]
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
indent_size = 2

[{*.java, *.gradle, *.yml, app/*package.json}]
indent_style = space
indent_size = 2
16 changes: 16 additions & 0 deletions README.alpha.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,25 @@ $ ./gradlew build nativeCompile &&\
build/native/nativeCompile/dns-proxy-server
```


## Run a container for testing

```
docker run --rm -it --hostname nginx.dev -e 'HOSTNAMES=nginx.com.br' nginx:1.15 bash
```
## x
```bash
docker-compose -f docker-compose-alpha.yml rm &&\
docker-compose -f docker-compose-alpha.yml build &&\
docker-compose -f docker-compose-alpha.yml run -T --rm arm7x86
```

Generate json reflect for all project

```
$ ./gradlew shadowJar

$ mkdir reflect &&\
$JAVA_HOME/bin/java -agentlib:native-image-agent=config-output-dir=./reflect -jar build/libs/dns-proxy-server*all.jar
```

34 changes: 31 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ buildscript {
plugins {
id "java"
id 'org.graalvm.buildtools.native' version '0.9.19'
id "com.github.johnrengelman.shadow" version "7.1.2"
}

repositories {
Expand Down Expand Up @@ -44,15 +45,24 @@ dependencies {
compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.+'
annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.+'

compileOnly(group: "com.mageddo.nativeimage", name: "reflection-config-generator", version: "2.3.+")
annotationProcessor(group: "com.mageddo.nativeimage", name: "reflection-config-generator", version: "2.3.+")

implementation 'com.google.dagger:dagger:2.44.+'
annotationProcessor 'com.google.dagger:dagger-compiler:2.44.+'

implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.+'
implementation group: 'com.mageddo.tinyserver', name: 'tinyserver', version: '1.0.+'
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.+'
implementation group: "ch.qos.logback", name: "logback-classic", version: "1.2.+"

implementation group: 'com.mageddo.tinyserver', name: 'tinyserver', version: '1.0.+'

implementation group: 'dnsjava', name: 'dnsjava', version: '3.5.2'

implementation group: 'com.github.docker-java', name: 'docker-java-core', version: '3.2.14'
implementation group: 'com.github.docker-java', name: 'docker-java-transport-httpclient5', version: '3.2.14'

compileOnly(group: "com.mageddo.nativeimage", name: "reflection-config-generator", version: "2.4.+")
annotationProcessor(group: "com.mageddo.nativeimage", name: "reflection-config-generator", version: "2.4.+")

testCompileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.+'
testAnnotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.+'
testImplementation(group: "org.junit.jupiter", name: "junit-jupiter", version: "5.8.+")
Expand All @@ -65,3 +75,21 @@ test {
events "passed", "skipped", "failed"
}
}


def mainClassName = "com.mageddo.dnsproxyserver.App"

jar {
manifest {
attributes(
"Main-Class": mainClassName
)
}
}

shadowJar {
mergeServiceFiles()
transform(com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer) {
mergeStrategy = "append"
}
}
14 changes: 10 additions & 4 deletions src/main/java/com/mageddo/dnsproxyserver/App.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package com.mageddo.dnsproxyserver;

public class App {
public static void main(String[] args) {
System.out.println("Hello World");
import com.mageddo.dnsproxyserver.dagger.Factory;

// start webserver
public class App {
public static void main(String[] args) throws InterruptedException {
final var factory = Factory.factory();

// start dns server
factory.dnsServerStarter().start();

// start webserver

// configurations

// setup as default dns

// install as service

Thread.currentThread().join();

}
}
20 changes: 20 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/config/Configs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.mageddo.dnsproxyserver.config;

import com.mageddo.dnsproxyserver.server.dns.solver.RemoteSolverConfig;
import com.mageddo.dnsproxyserver.server.dns.SimpleServer;

public class Configs {
public static int findDnsServerPort() {
return 8053;
}

public static SimpleServer.Protocol findDnsServerProtocol() {
return SimpleServer.Protocol.BOTH;
}

public static RemoteSolverConfig findRemoverSolverConfig() {
return new RemoteSolverConfig()
.setIp(new byte[]{8, 8, 8, 8})
.setPort((short) 53);
}
}
46 changes: 46 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/dagger/DockerModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.mageddo.dnsproxyserver.dagger;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import com.mageddo.dnsproxyserver.docker.DockerRepository;
import com.mageddo.dnsproxyserver.docker.DockerRepositoryDefault;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;

import java.time.Duration;

@Module
public interface DockerModule {


@Binds
DockerRepository bind(DockerRepositoryDefault m);

@Provides
static DockerClient dockerClient() {
final var config = DefaultDockerClientConfig.createDefaultConfigBuilder()
.withDockerHost("unix:///var/run/docker.sock")
.withDockerTlsVerify(false)
// .withDockerCertPath("/home/user/.docker")
// .withRegistryUsername(registryUser)
// .withRegistryPassword(registryPass)
// .withRegistryEmail(registryMail)
// .withRegistryUrl(registryUrl)
.build();

final var httpClient = new ApacheDockerHttpClient.Builder()
.dockerHost(config.getDockerHost())
.sslConfig(config.getSSLConfig())
.maxConnections(5)
.connectionTimeout(Duration.ofMillis(300))
.responseTimeout(Duration.ofSeconds(3))
.build();

return DockerClientImpl.getInstance(config, httpClient);
}


}
24 changes: 24 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/dagger/Factory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.mageddo.dnsproxyserver.dagger;

import com.mageddo.dnsproxyserver.server.dns.ServerStarter;
import com.mageddo.dnsproxyserver.server.dns.solver.Solver;
import dagger.Component;

import javax.inject.Singleton;
import java.util.Set;

@Singleton
@Component(modules = {MainModule.class, DockerModule.class})
public interface Factory {

ServerStarter dnsServerStarter();

Set<Solver> solvers();

static Factory factory() {
return DaggerFactory
.builder()
.build()
;
}
}
30 changes: 30 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/dagger/MainModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.mageddo.dnsproxyserver.dagger;

import com.mageddo.dnsproxyserver.config.Configs;
import com.mageddo.dnsproxyserver.server.dns.solver.DockerSolver;
import com.mageddo.dnsproxyserver.server.dns.solver.RemoteSolver;
import com.mageddo.dnsproxyserver.server.dns.solver.Solver;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.ElementsIntoSet;
import org.xbill.DNS.Resolver;
import org.xbill.DNS.SimpleResolver;

import java.util.Set;

@Module
public interface MainModule {

@ElementsIntoSet
@Provides
static Set<Solver> solvers(
RemoteSolver a, DockerSolver b
) {
return Set.of(a, b);
}

@Provides
static Resolver simpleResolver() {
return new SimpleResolver(Configs.findRemoverSolverConfig().toSocketAddress());
}
}
41 changes: 41 additions & 0 deletions src/main/java/com/mageddo/dnsproxyserver/docker/Docker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.mageddo.dnsproxyserver.docker;

import com.github.dockerjava.api.model.ContainerConfig;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

public class Docker {

public static final String HOSTNAME_ENV = "HOSTNAMES=";

public static String findContainerHostname(ContainerConfig config) {
final var hostname = config.getHostName();
if (StringUtils.isBlank(hostname)) {
return null;
}
final var domainName = config.getDomainName();
if (StringUtils.isBlank(domainName)) {
return hostname;
}
return String.format("%s.%s", hostname, domainName);
}

public static Set<String> findHostnameFromEnv(String[] envs) {
if (envs == null) {
return Collections.emptySet();
}
for (String env : envs) {
if (env.startsWith(HOSTNAME_ENV)) {
final var hosts = env.substring(HOSTNAME_ENV.length()).split("\s,\s");
return Arrays
.stream(hosts)
.collect(Collectors.toSet());
}
}
return Collections.emptySet();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.mageddo.dnsproxyserver.docker;

import com.github.dockerjava.api.command.InspectContainerResponse;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

@Slf4j
public class DockerNetworks {
public static String findBestIpMatching(InspectContainerResponse c, String... networksNames) {
final var networks = c.getNetworkSettings().getNetworks();
for (final var name : networksNames) {
if (!networks.containsKey(name)) {
continue;
}
final var ip = networks.get(name).getIpAddress();
log.debug("status=foundIp, network={}, container={}, ip={}", name, c.getName(), ip);
return ip;
}
log.debug("status=noIpFound, searchedNetworks={}, container={}", Arrays.toString(networksNames), c.getName());
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.mageddo.dnsproxyserver.docker;

public interface DockerRepository {
/**
*
* @param host
* @return the host ip
*/
mageddo marked this conversation as resolved.
Show resolved Hide resolved
String findHostIp(String host);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.mageddo.dnsproxyserver.docker;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.InspectContainerResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;

import static com.mageddo.dnsproxyserver.docker.Docker.findContainerHostname;
import static com.mageddo.dnsproxyserver.docker.Docker.findHostnameFromEnv;

@Slf4j
@Singleton
@AllArgsConstructor(onConstructor = @__({@Inject}))
public class DockerRepositoryDefault implements DockerRepository {

public static final String RUNNING_STATUS = "running";
private final DockerClient dockerClient;

@Override
public String findHostIp(String host) {
final var stopWatch = StopWatch.createStarted();
final var activeContainers = this.dockerClient
.listContainersCmd()
.withStatusFilter(Set.of(RUNNING_STATUS))
.withLimit(1024)
// .withNetworkFilter()
.exec();

final var foundIp = activeContainers
.stream()
.map(it -> this.dockerClient.inspectContainerCmd(it.getId()).exec())
.filter(matchingHostName(host))
.map(c -> DockerNetworks.findBestIpMatching(c, buildNetworks(c)))
.findFirst()
.orElse(null);
log.debug("status=findDone, host={}, found={}, time={}", host, foundIp, stopWatch.getTime());
return foundIp;
}

String[] buildNetworks(InspectContainerResponse c) {
return new String[]{"bridge"};
}

static Predicate<InspectContainerResponse> matchingHostName(String host) {
return it -> {
if (Objects.equals(findContainerHostname(it.getConfig()), host)) {
return true;
}
return findHostnameFromEnv(it.getConfig().getEnv()).contains(host);
};
}
}
Loading