Skip to content

Commit

Permalink
Merge pull request #13299 from rmuir/network_config_improvements
Browse files Browse the repository at this point in the history
Improve situation when network.host is set to wildcard (e.g. 0.0.0.0)
  • Loading branch information
rmuir committed Sep 3, 2015
2 parents ac9682d + 6bdf89c commit 4b01829
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 3 deletions.
Expand Up @@ -22,12 +22,13 @@
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
Expand Down Expand Up @@ -110,7 +111,26 @@ public InetAddress[] resolveBindHostAddress(String bindHost) throws IOException
if (bindHost == null) {
bindHost = DEFAULT_NETWORK_HOST;
}
return resolveInetAddress(bindHost);
InetAddress addresses[] = resolveInetAddress(bindHost);

// try to deal with some (mis)configuration
if (addresses != null) {
for (InetAddress address : addresses) {
// check if its multicast: flat out mistake
if (address.isMulticastAddress()) {
throw new IllegalArgumentException("bind address: {" + NetworkAddress.format(address) + "} is invalid: multicast address");
}
// check if its broadcast: flat out mistake
for (NetworkInterface nic : NetworkUtils.getInterfaces()) {
for (InterfaceAddress intf : nic.getInterfaceAddresses()) {
if (address.equals(intf.getBroadcast())) {
throw new IllegalArgumentException("bind address: {" + NetworkAddress.format(address) + "} is invalid: broadcast address");
}
}
}
}
}
return addresses;
}

// TODO: needs to be InetAddress[]
Expand All @@ -133,7 +153,31 @@ public InetAddress resolvePublishHostAddress(String publishHost) throws IOExcept
publishHost = DEFAULT_NETWORK_HOST;
}
// TODO: allow publishing multiple addresses
return resolveInetAddress(publishHost)[0];
InetAddress address = resolveInetAddress(publishHost)[0];

// try to deal with some (mis)configuration
if (address != null) {
// check if its multicast: flat out mistake
if (address.isMulticastAddress()) {
throw new IllegalArgumentException("publish address: {" + NetworkAddress.format(address) + "} is invalid: multicast address");
}
// check if its broadcast: flat out mistake
for (NetworkInterface nic : NetworkUtils.getInterfaces()) {
for (InterfaceAddress intf : nic.getInterfaceAddresses()) {
if (address.equals(intf.getBroadcast())) {
throw new IllegalArgumentException("publish address: {" + NetworkAddress.format(address) + "} is invalid: broadcast address");
}
}
}
// wildcard address, probably set by network.host
if (address.isAnyLocalAddress()) {
InetAddress old = address;
address = NetworkUtils.getFirstNonLoopbackAddresses()[0];
logger.warn("publish address: {{}} is a wildcard address, falling back to first non-loopback: {{}}",
NetworkAddress.format(old), NetworkAddress.format(address));
}
}
return address;
}

private InetAddress[] resolveInetAddress(String host) throws UnknownHostException, IOException {
Expand Down
@@ -0,0 +1,170 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.elasticsearch.common.network;

import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;

import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* Tests for network service... try to keep them safe depending upon configuration
* please don't actually bind to anything, just test the addresses.
*/
public class NetworkServiceTests extends ESTestCase {

/**
* ensure exception if we bind to multicast ipv4 address
*/
public void testBindMulticastV4() throws Exception {
NetworkService service = new NetworkService(Settings.EMPTY);
try {
service.resolveBindHostAddress("239.1.1.1");
fail("should have hit exception");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("invalid: multicast"));
}
}

/**
* ensure exception if we bind to multicast ipv6 address
*/
public void testBindMulticastV6() throws Exception {
NetworkService service = new NetworkService(Settings.EMPTY);
try {
service.resolveBindHostAddress("FF08::108");
fail("should have hit exception");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("invalid: multicast"));
}
}

/**
* ensure exception if we publish to multicast ipv4 address
*/
public void testPublishMulticastV4() throws Exception {
NetworkService service = new NetworkService(Settings.EMPTY);
try {
service.resolvePublishHostAddress("239.1.1.1");
fail("should have hit exception");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("invalid: multicast"));
}
}

/**
* ensure exception if we publish to multicast ipv6 address
*/
public void testPublishMulticastV6() throws Exception {
NetworkService service = new NetworkService(Settings.EMPTY);
try {
service.resolvePublishHostAddress("FF08::108");
fail("should have hit exception");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("invalid: multicast"));
}
}

/**
* ensure exception if we bind/publish to broadcast address
*/
public void testBindPublishBroadcast() throws Exception {
NetworkService service = new NetworkService(Settings.EMPTY);
// collect any broadcast addresses on the system
List<InetAddress> addresses = new ArrayList<>();
for (NetworkInterface nic : Collections.list(NetworkInterface.getNetworkInterfaces())) {
for (InterfaceAddress intf : nic.getInterfaceAddresses()) {
InetAddress address = intf.getBroadcast();
if (address != null) {
addresses.add(address);
}
}
}
// can easily happen (ipv6-only, localhost-only, ...)
assumeTrue("test requires broadcast addresses configured", addresses.size() > 0);
// make sure we fail on each one
for (InetAddress address : addresses) {
try {
service.resolveBindHostAddress(NetworkAddress.formatAddress(address));
fail("should have hit exception for broadcast address: " + address);
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("invalid: broadcast"));
}

try {
service.resolvePublishHostAddress(NetworkAddress.formatAddress(address));
fail("should have hit exception for broadcast address: " + address);
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("invalid: broadcast"));
}
}
}

/**
* ensure specifying wildcard ipv4 address will bind to all interfaces
*/
public void testBindAnyLocalV4() throws Exception {
NetworkService service = new NetworkService(Settings.EMPTY);
assertEquals(InetAddress.getByName("0.0.0.0"), service.resolveBindHostAddress("0.0.0.0")[0]);
}

/**
* ensure specifying wildcard ipv6 address will bind to all interfaces
*/
public void testBindAnyLocalV6() throws Exception {
NetworkService service = new NetworkService(Settings.EMPTY);
assertEquals(InetAddress.getByName("::"), service.resolveBindHostAddress("::")[0]);
}

/**
* ensure specifying wildcard ipv4 address selects reasonable publish address
*/
public void testPublishAnyLocalV4() throws Exception {
InetAddress expected = null;
try {
expected = NetworkUtils.getFirstNonLoopbackAddresses()[0];
} catch (Exception e) {
assumeNoException("test requires up-and-running non-loopback address", e);
}

NetworkService service = new NetworkService(Settings.EMPTY);
assertEquals(expected, service.resolvePublishHostAddress("0.0.0.0"));
}

/**
* ensure specifying wildcard ipv6 address selects reasonable publish address
*/
public void testPublishAnyLocalV6() throws Exception {
InetAddress expected = null;
try {
expected = NetworkUtils.getFirstNonLoopbackAddresses()[0];
} catch (Exception e) {
assumeNoException("test requires up-and-running non-loopback address", e);
}

NetworkService service = new NetworkService(Settings.EMPTY);
assertEquals(expected, service.resolvePublishHostAddress("::"));
}
}

0 comments on commit 4b01829

Please sign in to comment.