-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2424ed8
Showing
12 changed files
with
512 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Cloudflare & DynDNS | ||
|
||
Good for everyone who wants to use Cloudflare with their local ip but has a changing ip address. | ||
|
||
|
||
## Config | ||
```yaml | ||
# Your cloudflare api token | ||
apiToken: "" | ||
# Your cloudflare email (required for auth) | ||
cfEmail: "" | ||
# The zoneId of the zone you want to update (Can be seen on the right of the domain dashboard) | ||
zoneId: "" | ||
dnsRecords: | ||
- name: "myendpoint.example.com" | ||
type: "A" | ||
``` | ||
This project uses Cloudflare APIs only. It uses cloudflares cgi tracing endpoint to resolve the current public address and then handles changes accordingly. | ||
## How to run | ||
- Build with maven (java 11) | ||
- Run on a machine like a server or a Raspberry Pi | ||
- start once, edit configuration | ||
- start again | ||
## Motivation | ||
This is a simple project used by f.e. our smart home endpoints, nginx web server etc. | ||
Mental support provided by @iTzFreeHD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>de.tobiasgrether</groupId> | ||
<artifactId>CF-DynDNS</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
|
||
<properties> | ||
<log4j2.version>2.14.0</log4j2.version> | ||
</properties> | ||
<repositories> | ||
<repository> | ||
<id>jitpack.io</id> | ||
<url>https://jitpack.io</url> | ||
</repository> | ||
</repositories> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.ini4j</groupId> | ||
<artifactId>ini4j</artifactId> | ||
<version>0.5.4</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.yaml</groupId> | ||
<artifactId>snakeyaml</artifactId> | ||
<version>1.29</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.projectlombok</groupId> | ||
<artifactId>lombok</artifactId> | ||
<version>1.18.20</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.konghq</groupId> | ||
<artifactId>unirest-java</artifactId> | ||
<version>3.11.09</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-slf4j-impl</artifactId> | ||
<version>2.13.3</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-api</artifactId> | ||
<version>${log4j2.version}</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-core</artifactId> | ||
<version>${log4j2.version}</version> | ||
<scope>compile</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>3.8.1</version> | ||
<configuration> | ||
<source>11</source> | ||
<target>11</target> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<version>3.1.2</version> | ||
<configuration> | ||
<archive> | ||
<manifestEntries> | ||
<addClasspath>true</addClasspath> | ||
<classpathPrefix>lib/</classpathPrefix> | ||
<Main-Class>de.tobiasgrether.dyndns.Bootstrap</Main-Class> | ||
</manifestEntries> | ||
</archive> | ||
<finalName>DynDNS-Exporter</finalName> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
<version>1.6</version> | ||
<executions> | ||
<execution> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>shade</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package de.tobiasgrether.dyndns; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class Bootstrap { | ||
private static final Logger logger = LoggerFactory.getLogger("Main"); | ||
|
||
public static void main(String[] args){ | ||
logger.info("Starting up DynDNS.."); | ||
DynDNS dnsManager = new DynDNS(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package de.tobiasgrether.dyndns; | ||
|
||
import de.tobiasgrether.dyndns.model.DNSListResult; | ||
import de.tobiasgrether.dyndns.model.DNSRecord; | ||
import de.tobiasgrether.dyndns.model.config.ConfigModel; | ||
import de.tobiasgrether.dyndns.model.config.RecordEntry; | ||
import de.tobiasgrether.dyndns.util.ConfigParser; | ||
import kong.unirest.*; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.IOException; | ||
import java.io.StringReader; | ||
import java.util.Properties; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
public class DynDNS { | ||
|
||
private final Logger logger = LoggerFactory.getLogger("DynDNS"); | ||
|
||
private ConfigModel model; | ||
private String lastKnownAddress; | ||
private final ObjectMapper mapper = new JsonObjectMapper(); | ||
|
||
public DynDNS() { | ||
try { | ||
this.model = ConfigParser.parseConfig(this); | ||
} catch (IOException e) { | ||
this.logger.error("Error while parsing configuration file, exiting...", e); | ||
return; | ||
} | ||
|
||
ScheduledExecutorService requestRoundExecutor = Executors.newSingleThreadScheduledExecutor(); | ||
requestRoundExecutor.scheduleAtFixedRate(this::checkCurrentPublicIP, 0, 30, TimeUnit.SECONDS); | ||
} | ||
|
||
private void checkCurrentPublicIP() { | ||
HttpResponse<String> response = Unirest.get("https://cloudflare.com/cdn-cgi/trace") | ||
.asString(); | ||
|
||
if (response.getStatus() == 200) { | ||
try { | ||
Properties p = new Properties(); | ||
p.load(new StringReader(response.getBody())); | ||
String currentIp = p.getProperty("ip"); | ||
if (!currentIp.equals(this.lastKnownAddress)) { | ||
this.triggerDNSRewrite(currentIp); | ||
this.lastKnownAddress = currentIp; | ||
} | ||
} catch (Throwable t) { | ||
this.logger.error("Error while handling ini file", t); | ||
} | ||
|
||
} else { | ||
this.logger.warn("Could not parse current public ip from Cloudflare. Error " + response.getStatus() + ": " + response.getStatusText()); | ||
} | ||
} | ||
|
||
private void triggerDNSRewrite(String currentIp) { | ||
this.logger.warn("Detected new public ip, rewriting dns records.."); | ||
|
||
HttpResponse<JsonNode> result = Unirest.get("https://api.cloudflare.com/client/v4/zones/" + this.model.getZoneId() + "/dns_records") | ||
.header("X-Auth-Key", this.model.getApiToken()) | ||
.header("X-Auth-Email", this.model.getCfEmail()) | ||
.asJson(); | ||
|
||
DNSListResult parsedResult = this.mapper.readValue(result.getBody().toString(), DNSListResult.class); | ||
if (parsedResult.isSuccess()) { | ||
for (DNSRecord record : parsedResult.getResult()) { | ||
if (this.model.getDnsRecords().contains(new RecordEntry(record.getName(), "")) && !record.getContent().equals(currentIp)) { | ||
record.setContent(currentIp); | ||
HttpResponse<JsonNode> update = Unirest.put("https://api.cloudflare.com/client/v4/zones/" + this.model.getZoneId() + "/dns_records/" + record.getId()) | ||
.body(this.mapper.writeValue(record)) | ||
.header("X-Auth-Key", this.model.getApiToken()) | ||
.header("X-Auth-Email", this.model.getCfEmail()) | ||
.asJson(); | ||
if (update.getStatus() == 200) { | ||
this.logger.info("DNS Record updated: {} (Record type {}) now has IP {}", record.getName(), record.getType(), currentIp); | ||
} | ||
} | ||
} | ||
} | ||
this.logger.info("Record rewrite complete, new public ip is " + currentIp); | ||
} | ||
|
||
public Logger getLogger() { | ||
return logger; | ||
} | ||
|
||
public ConfigModel getModel() { | ||
return model; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/de/tobiasgrether/dyndns/model/CloudflareTraceResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package de.tobiasgrether.dyndns.model; | ||
|
||
import lombok.Getter; | ||
import lombok.ToString; | ||
|
||
@Getter | ||
@ToString | ||
public class CloudflareTraceResult { | ||
|
||
public Object fl; | ||
private String h; | ||
private String ip; | ||
private String ts; | ||
private String visit_scheme; | ||
private String uag; | ||
private String colo; | ||
private String http; | ||
private String loc; | ||
private String tls; | ||
private String sni; | ||
private boolean warp; | ||
private boolean gateway; | ||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/de/tobiasgrether/dyndns/model/DNSListResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package de.tobiasgrether.dyndns.model; | ||
|
||
import lombok.Getter; | ||
import lombok.ToString; | ||
|
||
@Getter | ||
@ToString | ||
public class DNSListResult { | ||
private boolean success; | ||
private DNSRecord[] result; | ||
} |
Oops, something went wrong.