diff --git a/source/common/network/utility.cc b/source/common/network/utility.cc index e7f7039e9a405..0bad71017980b 100644 --- a/source/common/network/utility.cc +++ b/source/common/network/utility.cc @@ -281,6 +281,44 @@ bool Utility::isLocalConnection(const Network::ConnectionSocket& socket) { return false; } +bool Utility::isLocalIpAddress(const Address::Instance& address) { + if (address.type() != Envoy::Network::Address::Type::Ip) { + return false; + } + + if (isLoopbackAddress(address)) { + return false; + } + + struct ifaddrs* ifaddr; + const int rc = getifaddrs(&ifaddr); + Cleanup ifaddr_cleanup([ifaddr] { + if (ifaddr) { + freeifaddrs(ifaddr); + } + }); + RELEASE_ASSERT(rc == 0, ""); + + auto af_look_up = (address.ip()->version() == Address::IpVersion::v4) ? AF_INET : AF_INET6; + + for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == nullptr) { + continue; + } + + if (ifa->ifa_addr->sa_family == af_look_up) { + const auto* addr = reinterpret_cast(ifa->ifa_addr); + auto local_address = Address::addressFromSockAddr( + *addr, (af_look_up == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6)); + + if (address == *local_address) { + return true; + } + } + } + return false; +} + bool Utility::isInternalAddress(const Address::Instance& address) { if (address.type() != Address::Type::Ip) { return false; diff --git a/source/common/network/utility.h b/source/common/network/utility.h index 68f56d7ec5491..a75b682a3540c 100644 --- a/source/common/network/utility.h +++ b/source/common/network/utility.h @@ -139,6 +139,12 @@ class Utility { */ static bool isLocalConnection(const Network::ConnectionSocket& socket); + /** + * Determine whether this is a local address. + * @return bool the address is a local address. + */ + static bool isLocalIpAddress(const Address::Instance& address); + /** * Determine whether this is an internal (RFC1918) address. * @return bool the address is an RFC1918 address. diff --git a/source/server/connection_handler_impl.cc b/source/server/connection_handler_impl.cc index 855cdaadb7e3e..7588973e3470e 100644 --- a/source/server/connection_handler_impl.cc +++ b/source/server/connection_handler_impl.cc @@ -126,6 +126,27 @@ ConnectionHandlerImpl::findActiveListenerByAddress(const Network::Address::Insta return listener_it->second.get(); } + /* + * istio: if the ip is local pod ip, select the predefined listener + * 1. where can I find the pod ip? + * env: INSTANCE_IP: (v1:status.podIP) + * + * 2. What the predefined listener should be? + */ + if (Network::Utility::isLocalIpAddress(address)) { + ENVOY_LOG_TO_LOGGER( + logger_, error, + "dest ip {} is local address but hit no listener, try using blackhole listener", + address.ip()->addressAsString()); + listener_it = std::find_if( + listeners_.begin(), listeners_.end(), + [](const std::pair& p) { + return p.second->config_.name() == "ISTIO_WILDCARD_PORT_LISTENER"; + }); + if (listener_it != listeners_.end()) { + return listener_it->second.get(); + } + } // Otherwise, we need to look for the wild card match, i.e., 0.0.0.0:[address_port]. // We do not return stopped listeners. // TODO(wattli): consolidate with previous search for more efficiency.