Skip to content

Commit

Permalink
Add support for IPv6 wildcard addresses in HttpConfiguration
Browse files Browse the repository at this point in the history
  • Loading branch information
Jochen Schalanda committed Oct 4, 2017
1 parent becbce7 commit 9500a81
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.graylog2.configuration;

import com.github.joschi.jadconfig.Parameter;
import com.github.joschi.jadconfig.ParameterException;
import com.github.joschi.jadconfig.ValidationException;
import com.github.joschi.jadconfig.ValidatorMethod;
import com.github.joschi.jadconfig.validators.PositiveIntegerValidator;
Expand All @@ -28,6 +29,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -38,7 +41,6 @@
public class HttpConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(HttpConfiguration.class);

private static final String WILDCARD_IP_ADDRESS = "0.0.0.0";
private static final int GRAYLOG_DEFAULT_PORT = 9000;

public static final String OVERRIDE_HEADER = "X-Graylog-Server-URL";
Expand Down Expand Up @@ -91,17 +93,30 @@ public String getUriScheme() {
return isHttpEnableTls() ? "https" : "http";
}

@Nullable
private InetAddress toInetAddress(String host) {
try {
return InetAddress.getByName(host);
} catch (UnknownHostException e) {
LOG.debug("Couldn't resolve \"{}\"", host, e);
return null;
}
}

public URI getHttpPublishUri() {
if (httpPublishUri == null) {
final URI defaultHttpUri = getDefaultHttpUri();
LOG.debug("No \"http_publish_uri\" set. Using default <{}>.", defaultHttpUri);
return defaultHttpUri;
} else if (WILDCARD_IP_ADDRESS.equals(httpPublishUri.getHost())) {
final URI defaultHttpUri = getDefaultHttpUri(httpPublishUri.getPath());
LOG.warn("\"{}\" is not a valid setting for \"http_publish_uri\". Using default <{}>.", httpPublishUri, defaultHttpUri);
return defaultHttpUri;
} else {
return Tools.normalizeURI(httpPublishUri, httpPublishUri.getScheme(), GRAYLOG_DEFAULT_PORT, httpPublishUri.getPath());
final InetAddress inetAddress = toInetAddress(httpPublishUri.getHost());
if (Tools.isWildcardInetAddress(inetAddress)) {
final URI defaultHttpUri = getDefaultHttpUri(httpPublishUri.getPath());
LOG.warn("\"{}\" is not a valid setting for \"http_publish_uri\". Using default <{}>.", httpPublishUri, defaultHttpUri);
return defaultHttpUri;
} else {
return Tools.normalizeURI(httpPublishUri, httpPublishUri.getScheme(), GRAYLOG_DEFAULT_PORT, httpPublishUri.getPath());
}
}
}

Expand All @@ -114,17 +129,18 @@ private URI getDefaultHttpUri(String path) {
final HostAndPort bindAddress = getHttpBindAddress();

final URI publishUri;
if (WILDCARD_IP_ADDRESS.equals(bindAddress.getHost())) {
final InetAddress inetAddress = toInetAddress(bindAddress.getHost());
if (inetAddress != null && Tools.isWildcardInetAddress(inetAddress)) {
final InetAddress guessedAddress;
try {
guessedAddress = Tools.guessPrimaryNetworkAddress();
guessedAddress = Tools.guessPrimaryNetworkAddress(inetAddress instanceof Inet4Address);

if (guessedAddress.isLoopbackAddress()) {
LOG.debug("Using loopback address {}", guessedAddress);
}
} catch (Exception e) {
LOG.error("Could not guess primary network address for \"http_publish_uri\". Please configure it in your Graylog configuration.", e);
throw new RuntimeException("No http_publish_uri.", e);
throw new ParameterException("No http_publish_uri.", e);
}

try {
Expand Down Expand Up @@ -204,7 +220,7 @@ public URI getHttpExternalUri() {
public void validateHttpBindAddress() throws ValidationException {
try {
final String host = getHttpBindAddress().getHost();
if(!InetAddresses.isInetAddress(host)) {
if (!InetAddresses.isInetAddress(host)) {
final InetAddress inetAddress = InetAddress.getByName(host);
}
} catch (IllegalArgumentException | UnknownHostException e) {
Expand All @@ -215,15 +231,15 @@ public void validateHttpBindAddress() throws ValidationException {
@ValidatorMethod
@SuppressWarnings("unused")
public void validateHttpPublishUriPathEndsWithSlash() throws ValidationException {
if(!getHttpPublishUri().getPath().endsWith("/")) {
if (!getHttpPublishUri().getPath().endsWith("/")) {
throw new ValidationException("\"http_publish_uri\" must end with a slash (\"/\")");
}
}

@ValidatorMethod
@SuppressWarnings("unused")
public void validateHttpExternalUriPathEndsWithSlash() throws ValidationException {
if(!getHttpExternalUri().getPath().endsWith("/")) {
if (!getHttpExternalUri().getPath().endsWith("/")) {
throw new ValidationException("\"http_external_uri\" must end with a slash (\"/\")");
}
}
Expand Down
15 changes: 13 additions & 2 deletions graylog2-server/src/main/java/org/graylog2/plugin/Tools.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
Expand All @@ -61,6 +63,8 @@
* Utility class for various tool/helper functions.
*/
public final class Tools {
private static final byte[] EMPTY_BYTE_ARRAY_4 = {0,0,0,0};
private static final byte[] EMPTY_BYTE_ARRAY_16 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

public static final String ES_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String ES_DATE_FORMAT_NO_MS = "yyyy-MM-dd HH:mm:ss";
Expand Down Expand Up @@ -451,15 +455,18 @@ public static Number getNumber(Object o, Number defaultValue) {
* or the loopback address as fallback.
* @throws SocketException if the list of network interfaces couldn't be retrieved
*/
public static InetAddress guessPrimaryNetworkAddress() throws SocketException {
public static InetAddress guessPrimaryNetworkAddress(boolean preferIPv4) throws SocketException {
final Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

if (interfaces != null) {
for (NetworkInterface interf : Collections.list(interfaces)) {
if (!interf.isLoopback() && interf.isUp()) {
// Interface is not loopback and up. Try to get the first address.
for (InetAddress addr : Collections.list(interf.getInetAddresses())) {
if (addr instanceof Inet4Address) {
if (preferIPv4 && addr instanceof Inet4Address) {
return addr;
}
if (!preferIPv4 && addr instanceof Inet6Address) {
return addr;
}
}
Expand All @@ -470,6 +477,10 @@ public static InetAddress guessPrimaryNetworkAddress() throws SocketException {
return InetAddress.getLoopbackAddress();
}

public static boolean isWildcardInetAddress(@Nullable InetAddress inetAddress) {
return inetAddress != null && (Arrays.equals(EMPTY_BYTE_ARRAY_4, inetAddress.getAddress()) || Arrays.equals(EMPTY_BYTE_ARRAY_16, inetAddress.getAddress()));
}

@Nullable
public static URI getUriWithPort(@Nullable final URI uri, final int port) {
if (uri == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ public void testHttpBindAddressWildcard() throws RepositoryException, Validation
.isNotEqualTo(URI.create("http://0.0.0.0:9000"));
}

@Test
public void testHttpBindAddressIPv6Wildcard() throws RepositoryException, ValidationException {
jadConfig.setRepository(new InMemoryRepository(ImmutableMap.of("http_bind_address", "[::]:9000"))).addConfigurationBean(configuration).process();

assertThat(configuration.getDefaultHttpUri())
.isNotNull()
.isNotEqualTo(URI.create("http://[::]:9000"));
}

@Test
public void testHttpPublishUriWildcard() throws RepositoryException, ValidationException {
final Map<String, String> properties = ImmutableMap.of(
Expand All @@ -163,6 +172,17 @@ public void testHttpPublishUriWildcard() throws RepositoryException, ValidationE
assertThat(configuration.getHttpPublishUri()).isNotEqualTo(URI.create("http://0.0.0.0:9000/"));
}

@Test
public void testHttpPublishUriIPv6Wildcard() throws RepositoryException, ValidationException {
final Map<String, String> properties = ImmutableMap.of(
"http_bind_address", "[::]:9000",
"http_publish_uri", "http://[::]:9000/");

jadConfig.setRepository(new InMemoryRepository(properties)).addConfigurationBean(configuration).process();

assertThat(configuration.getHttpPublishUri()).isNotEqualTo(URI.create("http://[::]:9000/"));
}

@Test
public void testHttpPublishUriWildcardKeepsPath() throws RepositoryException, ValidationException {
final Map<String, String> properties = ImmutableMap.of(
Expand All @@ -176,6 +196,19 @@ public void testHttpPublishUriWildcardKeepsPath() throws RepositoryException, Va
.isNotEqualTo(URI.create("http://0.0.0.0:9000/api/"));
}

@Test
public void testHttpPublishUriIPv6WildcardKeepsPath() throws RepositoryException, ValidationException {
final Map<String, String> properties = ImmutableMap.of(
"http_bind_address", "[::]:9000",
"http_publish_uri", "http://[::]:9000/api/");

jadConfig.setRepository(new InMemoryRepository(properties)).addConfigurationBean(configuration).process();

assertThat(configuration.getHttpPublishUri())
.hasPath("/api/")
.isNotEqualTo(URI.create("http://[::]:9000/api/"));
}

@Test
public void testHttpPublishUriCustomAddress() throws RepositoryException, ValidationException {
jadConfig.setRepository(new InMemoryRepository(ImmutableMap.of("http_bind_address", "10.0.0.1:9000"))).addConfigurationBean(configuration).process();
Expand Down
13 changes: 13 additions & 0 deletions graylog2-server/src/test/java/org/graylog2/plugin/ToolsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@

import com.google.common.collect.Lists;
import com.google.common.io.Resources;
import com.google.common.net.InetAddresses;
import org.graylog2.inputs.TestHelper;
import org.joda.time.DateTime;
import org.junit.Test;

import java.io.EOFException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
Expand Down Expand Up @@ -323,4 +325,15 @@ public void normalizeURIReturnsNormalizedURI() {
public void normalizeURIReturnsNullIfURIIsNull() {
assertNull(Tools.normalizeURI(null, "http", 1234, "/baz"));
}

@Test
public void isWildcardAddress() {
assertTrue(Tools.isWildcardInetAddress(InetAddresses.forString("0.0.0.0")));
assertTrue(Tools.isWildcardInetAddress(InetAddresses.forString("::")));
assertFalse(Tools.isWildcardInetAddress(null));
assertFalse(Tools.isWildcardInetAddress(InetAddresses.forString("127.0.0.1")));
assertFalse(Tools.isWildcardInetAddress(InetAddresses.forString("::1")));
assertFalse(Tools.isWildcardInetAddress(InetAddresses.forString("198.51.100.23")));
assertFalse(Tools.isWildcardInetAddress(InetAddresses.forString("2001:DB8::42")));
}
}

0 comments on commit 9500a81

Please sign in to comment.