mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-02-03 05:51:28 +01:00
Add support for dynamic DNS in IP Allowlist
Affects issues: - Close #1502
This commit is contained in:
parent
93c10ccdcd
commit
b2d78bb491
@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.web.ResourceWriteTask;
|
|||||||
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.configuration.AddressAllowList;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
||||||
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
||||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||||
@ -108,4 +109,8 @@ public interface BukkitTaskModule {
|
|||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
TaskSystem.Task bindPlaceholderWarmupTask(PlaceholderCacheRefreshTask placeholderCacheRefreshTask);
|
TaskSystem.Task bindPlaceholderWarmupTask(PlaceholderCacheRefreshTask placeholderCacheRefreshTask);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
TaskSystem.Task bindAddressAllowListUpdateTask(AddressAllowList addressAllowList);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.ResourceWriteTask;
|
|||||||
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.configuration.AddressAllowList;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
||||||
import com.djrapitops.plan.gathering.timed.BungeePingCounter;
|
import com.djrapitops.plan.gathering.timed.BungeePingCounter;
|
||||||
import com.djrapitops.plan.gathering.timed.ProxyTPSCounter;
|
import com.djrapitops.plan.gathering.timed.ProxyTPSCounter;
|
||||||
@ -87,4 +88,8 @@ public interface BungeeTaskModule {
|
|||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
TaskSystem.Task bindAddressAllowListUpdateTask(AddressAllowList addressAllowList);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Player Analytics (Plan).
|
||||||
|
*
|
||||||
|
* Plan is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Plan is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.delivery.webserver.configuration;
|
||||||
|
|
||||||
|
import com.djrapitops.plan.TaskSystem;
|
||||||
|
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||||
|
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
|
||||||
|
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maintains Dynamic IP and other IPs in IP Allowlist.
|
||||||
|
* <p>
|
||||||
|
* If the allowlist is disabled this task is not registered.
|
||||||
|
*
|
||||||
|
* @author AuroraLS3
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class AddressAllowList extends TaskSystem.Task {
|
||||||
|
|
||||||
|
private final PlanConfig config;
|
||||||
|
|
||||||
|
private List<String> addresses = new ArrayList<>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AddressAllowList(PlanConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> resolveIpAddress(String host) {
|
||||||
|
try {
|
||||||
|
InetAddress[] foundIps = InetAddress.getAllByName(host);
|
||||||
|
return Arrays.stream(foundIps)
|
||||||
|
.map(InetAddress::getHostAddress)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register(RunnableFactory runnableFactory) {
|
||||||
|
if (config.isFalse(WebserverSettings.IP_WHITELIST)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runnableFactory.create(this).runTaskTimerAsynchronously(0, 60, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateDnsEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDnsEntries() {
|
||||||
|
List<String> configuredAddresses = config.get(WebserverSettings.WHITELIST);
|
||||||
|
List<String> allowedAddresses = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String configuredAddress : configuredAddresses) {
|
||||||
|
if (configuredAddress.startsWith("dns:")) {
|
||||||
|
allowedAddresses.addAll(resolveIpAddress(configuredAddress.substring(4)));
|
||||||
|
} else {
|
||||||
|
allowedAddresses.add(configuredAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses = allowedAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAllowedAddresses() {
|
||||||
|
return addresses;
|
||||||
|
}
|
||||||
|
}
|
@ -18,8 +18,6 @@ package com.djrapitops.plan.delivery.webserver.configuration;
|
|||||||
|
|
||||||
import com.djrapitops.plan.exceptions.EnableException;
|
import com.djrapitops.plan.exceptions.EnableException;
|
||||||
import com.djrapitops.plan.exceptions.LibraryLoadingException;
|
import com.djrapitops.plan.exceptions.LibraryLoadingException;
|
||||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
|
||||||
import com.djrapitops.plan.settings.config.paths.WebserverSettings;
|
|
||||||
import com.djrapitops.plan.storage.file.PlanFiles;
|
import com.djrapitops.plan.storage.file.PlanFiles;
|
||||||
import com.djrapitops.plan.utilities.dev.Untrusted;
|
import com.djrapitops.plan.utilities.dev.Untrusted;
|
||||||
import dev.vankka.dependencydownload.DependencyManager;
|
import dev.vankka.dependencydownload.DependencyManager;
|
||||||
@ -46,15 +44,15 @@ public class IpAllowListMatcher {
|
|||||||
|
|
||||||
private final PluginLogger logger;
|
private final PluginLogger logger;
|
||||||
private final PlanFiles files;
|
private final PlanFiles files;
|
||||||
private final PlanConfig config;
|
private final AddressAllowList addressAllowList;
|
||||||
private final AtomicBoolean failedDownload = new AtomicBoolean(false);
|
private final AtomicBoolean failedDownload = new AtomicBoolean(false);
|
||||||
private ClassLoader libraryClassLoader;
|
private ClassLoader libraryClassLoader;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public IpAllowListMatcher(PluginLogger logger, PlanFiles files, PlanConfig config) {
|
public IpAllowListMatcher(PluginLogger logger, PlanFiles files, AddressAllowList addressAllowList) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.files = files;
|
this.files = files;
|
||||||
this.config = config;
|
this.addressAllowList = addressAllowList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void prepare() {
|
public synchronized void prepare() {
|
||||||
@ -95,7 +93,7 @@ public class IpAllowListMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<String> addresses = config.get(WebserverSettings.WHITELIST);
|
List<String> addresses = addressAllowList.getAllowedAddresses();
|
||||||
IPLibraryAccessor libraryAccessor = new IPLibraryAccessor(libraryClassLoader);
|
IPLibraryAccessor libraryAccessor = new IPLibraryAccessor(libraryClassLoader);
|
||||||
return libraryAccessor.isAllowed(accessAddress, addresses);
|
return libraryAccessor.isAllowed(accessAddress, addresses);
|
||||||
} catch (LibraryLoadingException e) {
|
} catch (LibraryLoadingException e) {
|
||||||
@ -105,7 +103,7 @@ public class IpAllowListMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean exactMatchAllowCheck(@Untrusted String accessAddress) {
|
private boolean exactMatchAllowCheck(@Untrusted String accessAddress) {
|
||||||
List<String> allowed = config.get(WebserverSettings.WHITELIST);
|
List<String> allowed = addressAllowList.getAllowedAddresses();
|
||||||
return allowed.isEmpty() || allowed.contains(accessAddress);
|
return allowed.isEmpty() || allowed.contains(accessAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ Webserver:
|
|||||||
# IPv4 exact: "192.168.0.1", wildcard: "192.168.*.*", cidr: "192.168.0.0/16"
|
# IPv4 exact: "192.168.0.1", wildcard: "192.168.*.*", cidr: "192.168.0.0/16"
|
||||||
# IPv6 exact: "0:0:0:0:0:0:0:1", compressed: "1::1", cidr: "1234:db8:1234:1a:20::/64"
|
# IPv6 exact: "0:0:0:0:0:0:0:1", compressed: "1::1", cidr: "1234:db8:1234:1a:20::/64"
|
||||||
# More: https://seancfoley.github.io/IPAddress/ipaddress.html#supported-ip-address-parsing-formats
|
# More: https://seancfoley.github.io/IPAddress/ipaddress.html#supported-ip-address-parsing-formats
|
||||||
|
# Dynamic DNS hostname: "dns:intranet.example.com", updated once per minute
|
||||||
Whitelist:
|
Whitelist:
|
||||||
- "192.168.0.0"
|
- "192.168.0.0"
|
||||||
- "0:0:0:0:0:0:0:1"
|
- "0:0:0:0:0:0:0:1"
|
||||||
|
@ -79,6 +79,7 @@ Webserver:
|
|||||||
# IPv4 exact: "192.168.0.1", wildcard: "192.168.*.*", cidr: "192.168.0.0/16"
|
# IPv4 exact: "192.168.0.1", wildcard: "192.168.*.*", cidr: "192.168.0.0/16"
|
||||||
# IPv6 exact: "0:0:0:0:0:0:0:1", compressed: "1::1", cidr: "1234:db8:1234:1a:20::/64"
|
# IPv6 exact: "0:0:0:0:0:0:0:1", compressed: "1::1", cidr: "1234:db8:1234:1a:20::/64"
|
||||||
# More: https://seancfoley.github.io/IPAddress/ipaddress.html#supported-ip-address-parsing-formats
|
# More: https://seancfoley.github.io/IPAddress/ipaddress.html#supported-ip-address-parsing-formats
|
||||||
|
# Dynamic DNS hostname: "dns:intranet.example.com", updated once per minute
|
||||||
Whitelist:
|
Whitelist:
|
||||||
- "192.168.0.0"
|
- "192.168.0.0"
|
||||||
- "0:0:0:0:0:0:0:1"
|
- "0:0:0:0:0:0:0:1"
|
||||||
|
@ -20,6 +20,7 @@ import com.djrapitops.plan.TaskSystem;
|
|||||||
import com.djrapitops.plan.delivery.web.ResourceWriteTask;
|
import com.djrapitops.plan.delivery.web.ResourceWriteTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.configuration.AddressAllowList;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
||||||
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
||||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||||
@ -93,4 +94,8 @@ public interface FabricTaskModule {
|
|||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
TaskSystem.Task bindAddressAllowListUpdateTask(AddressAllowList addressAllowList);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import com.djrapitops.plan.delivery.web.ResourceWriteTask;
|
|||||||
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.configuration.AddressAllowList;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
||||||
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
||||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||||
@ -98,4 +99,8 @@ public interface NukkitTaskModule {
|
|||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
TaskSystem.Task bindAddressAllowListUpdateTask(AddressAllowList addressAllowList);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.ResourceWriteTask;
|
|||||||
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.configuration.AddressAllowList;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
||||||
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
import com.djrapitops.plan.gathering.ShutdownDataPreservation;
|
||||||
import com.djrapitops.plan.gathering.ShutdownHook;
|
import com.djrapitops.plan.gathering.ShutdownHook;
|
||||||
@ -98,4 +99,8 @@ public interface SpongeTaskModule {
|
|||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
TaskSystem.Task bindAddressAllowListUpdateTask(AddressAllowList addressAllowList);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.web.ResourceWriteTask;
|
|||||||
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
import com.djrapitops.plan.delivery.web.WebAssetVersionCheckTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
import com.djrapitops.plan.delivery.webserver.auth.ActiveCookieExpiryCleanupTask;
|
||||||
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
import com.djrapitops.plan.delivery.webserver.cache.JSONFileStorage;
|
||||||
|
import com.djrapitops.plan.delivery.webserver.configuration.AddressAllowList;
|
||||||
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
import com.djrapitops.plan.extension.ExtensionServerDataUpdater;
|
||||||
import com.djrapitops.plan.gathering.timed.ProxyTPSCounter;
|
import com.djrapitops.plan.gathering.timed.ProxyTPSCounter;
|
||||||
import com.djrapitops.plan.gathering.timed.SystemUsageBuffer;
|
import com.djrapitops.plan.gathering.timed.SystemUsageBuffer;
|
||||||
@ -87,4 +88,8 @@ public interface VelocityTaskModule {
|
|||||||
@Binds
|
@Binds
|
||||||
@IntoSet
|
@IntoSet
|
||||||
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
TaskSystem.Task bindActiveCookieStoreExpiryTask(ActiveCookieExpiryCleanupTask activeCookieExpiryCleanupTask);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoSet
|
||||||
|
TaskSystem.Task bindAddressAllowListUpdateTask(AddressAllowList addressAllowList);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user