Improve situation when network.host is set to wildcard (e.g. 0.0.0.0)
Users might specify something like -Des.network.host=0.0.0.0, as that was the old default with previous versions of elasticsearch. This means to bind to all interfaces, but it makes no sense as a publish address. Pick a good one in this case, just like we do in other cases where publish isn't explicitly specified and we are bound to multiple (e.g. when configured by interface, or dns hostname with multiple addresses). However, in this case warn the user about it: since its arbitrarily picking the first non-loopback address like the old versions did, thats a little too heuristical, but lets make the cutover easy. Separately, fail hard if things like multicast or broadcast addresses are configured as bind or publish addresses, as that is simply invalid. Closes #13274
This commit is contained in:
parent
2a129f1868
commit
6bdf89c47e
|
@ -22,12 +22,13 @@ package org.elasticsearch.common.network;
|
||||||
import org.elasticsearch.common.component.AbstractComponent;
|
import org.elasticsearch.common.component.AbstractComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
|
||||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.InterfaceAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
@ -110,7 +111,26 @@ public class NetworkService extends AbstractComponent {
|
||||||
if (bindHost == null) {
|
if (bindHost == null) {
|
||||||
bindHost = DEFAULT_NETWORK_HOST;
|
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[]
|
// TODO: needs to be InetAddress[]
|
||||||
|
@ -133,7 +153,31 @@ public class NetworkService extends AbstractComponent {
|
||||||
publishHost = DEFAULT_NETWORK_HOST;
|
publishHost = DEFAULT_NETWORK_HOST;
|
||||||
}
|
}
|
||||||
// TODO: allow publishing multiple addresses
|
// 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 {
|
private InetAddress[] resolveInetAddress(String host) throws UnknownHostException, IOException {
|
||||||
|
|
|
@ -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("::"));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue