From df6394a83c8d47d656622ad070f86dc94a19f1f3 Mon Sep 17 00:00:00 2001 From: JP Simard Date: Mon, 27 Jun 2022 16:11:32 -0400 Subject: [PATCH] iOS: add `forceIPv6(...)` builder option Signed-off-by: JP Simard --- docs/root/api/starting_envoy.rst | 16 ++++++++++++++++ docs/root/intro/version_history.rst | 2 +- envoy | 2 +- library/common/config/config.cc | 6 +++--- .../envoymobile/engine/EnvoyConfiguration.java | 2 +- library/objective-c/EnvoyConfiguration.m | 3 +++ library/objective-c/EnvoyEngine.h | 2 ++ library/swift/EngineBuilder.swift | 14 ++++++++++++++ .../engine/EnvoyConfigurationTest.kt | 4 ++-- test/swift/EngineBuilderTests.swift | 17 +++++++++++++++++ .../apps/experimental/ViewController.swift | 12 ++++++++++-- 11 files changed, 70 insertions(+), 10 deletions(-) diff --git a/docs/root/api/starting_envoy.rst b/docs/root/api/starting_envoy.rst index 841d4442db..a8a62c3e90 100644 --- a/docs/root/api/starting_envoy.rst +++ b/docs/root/api/starting_envoy.rst @@ -487,6 +487,22 @@ SharedPreferences. // Coming soon. +~~~~~~~~~~~~~~~~~~~~~~~~~~ +``forceIPv6`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Specify whether to remap IPv4 addresses to the IPv6 space and always force connections +to use IPv6. Note this is an experimental option and should be enabled with caution. + +**Example**:: + + // Kotlin + builder.forceIPv6(true) + + // Swift + builder.forceIPv6(true) + + ---------------------- Advanced configuration ---------------------- diff --git a/docs/root/intro/version_history.rst b/docs/root/intro/version_history.rst index a32a3b08bf..63d20a4714 100644 --- a/docs/root/intro/version_history.rst +++ b/docs/root/intro/version_history.rst @@ -8,8 +8,8 @@ Breaking changes: - api: replace the ``drainConnections()`` method with a broader ``resetConnectivityState()``. (:issue:`#2225 <2225>`). - api: disallow setting 'host' header directly (:issue:`#2275 <2275>`) +- api: add experimental option to force all connections to use IPv6 (:issue: `#2379 <2379>`, :issue: `#2396 <2396>`) - android: respect Android's NetworkSecurityPolicy isCleartextTrafficPermitted APIs. -- android: add experimental option to force all connections to use IPv6 (:issue: `#2379 <2379>`) - net: enable happy eyeballs by default (:issue:`#2272 <2272>`) - iOS: remove support for installing via CocoaPods, which had not worked since 2020 (:issue:`#2215 <2215>`) - iOS: enable usage of ``NWPathMonitor`` by default (:issue:`#2329 <2329>`) diff --git a/envoy b/envoy index e792008a66..f96f342597 160000 --- a/envoy +++ b/envoy @@ -1 +1 @@ -Subproject commit e792008a66f744996fb30faeb7207ba642938551 +Subproject commit f96f342597c8d80891b7d9379e1f4c4fd28a190c diff --git a/library/common/config/config.cc b/library/common/config/config.cc index f17d52dcf5..de6a619eb4 100644 --- a/library/common/config/config.cc +++ b/library/common/config/config.cc @@ -78,16 +78,16 @@ const char* brotli_config_insert = R"( // clang-format off const std::string config_header = R"( !ignore default_defs: -- &android_force_ipv6 false - &connect_timeout 30s - &dns_fail_base_interval 2s - &dns_fail_max_interval 10s -- &dns_query_timeout 25s - &dns_lookup_family ALL - &dns_min_refresh_rate 60s - &dns_multiple_addresses true - &dns_preresolve_hostnames [] +- &dns_query_timeout 25s - &dns_refresh_rate 60s +- &force_ipv6 false )" #if defined(__APPLE__) R"(- &dns_resolver_name envoy.network.dns_resolver.apple @@ -514,7 +514,7 @@ stats_sinks: *stats_sinks disallow_global_stats: true reloadable_features: allow_multiple_dns_addresses: *dns_multiple_addresses - android_always_use_v6: *android_force_ipv6 + always_use_v6: *force_ipv6 http2_delay_keepalive_timeout: *h2_delay_keepalive_timeout )" // Needed due to warning in diff --git a/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java b/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java index f8954a3ab1..f0612e79bf 100644 --- a/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java +++ b/library/java/io/envoyproxy/envoymobile/engine/EnvoyConfiguration.java @@ -253,7 +253,7 @@ String resolveTemplate(final String configTemplate, final String platformFilterT enableDrainPostDnsRefresh ? "true" : "false")) .append(String.format("- &enable_interface_binding %s\n", enableInterfaceBinding ? "true" : "false")) - .append(String.format("- &android_force_ipv6 %s\n", forceIPv6 ? "true" : "false")) + .append(String.format("- &force_ipv6 %s\n", forceIPv6 ? "true" : "false")) .append(String.format("- &h2_connection_keepalive_idle_interval %ss\n", h2ConnectionKeepaliveIdleIntervalMilliseconds / 1000.0)) .append(String.format("- &h2_connection_keepalive_timeout %ss\n", diff --git a/library/objective-c/EnvoyConfiguration.m b/library/objective-c/EnvoyConfiguration.m index 41a36f9a54..a81dd6bc3d 100644 --- a/library/objective-c/EnvoyConfiguration.m +++ b/library/objective-c/EnvoyConfiguration.m @@ -19,6 +19,7 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled enableInterfaceBinding:(BOOL)enableInterfaceBinding enableDrainPostDnsRefresh:(BOOL)enableDrainPostDnsRefresh enforceTrustChainVerification:(BOOL)enforceTrustChainVerification + forceIPv6:(BOOL)forceIPv6 h2ConnectionKeepaliveIdleIntervalMilliseconds: (UInt32)h2ConnectionKeepaliveIdleIntervalMilliseconds h2ConnectionKeepaliveTimeoutSeconds:(UInt32)h2ConnectionKeepaliveTimeoutSeconds @@ -63,6 +64,7 @@ - (instancetype)initWithAdminInterfaceEnabled:(BOOL)adminInterfaceEnabled self.enableInterfaceBinding = enableInterfaceBinding; self.enableDrainPostDnsRefresh = enableDrainPostDnsRefresh; self.enforceTrustChainVerification = enforceTrustChainVerification; + self.forceIPv6 = forceIPv6; self.h2ConnectionKeepaliveIdleIntervalMilliseconds = h2ConnectionKeepaliveIdleIntervalMilliseconds; self.h2ConnectionKeepaliveTimeoutSeconds = h2ConnectionKeepaliveTimeoutSeconds; @@ -180,6 +182,7 @@ - (nullable NSString *)resolveTemplate:(NSString *)templateYAML { [definitions appendFormat:@"- &trust_chain_verification %@\n", self.enforceTrustChainVerification ? @"VERIFY_TRUST_CHAIN" : @"ACCEPT_UNTRUSTED"]; + [definitions appendFormat:@"- &force_ipv6 %@\n", self.forceIPv6 ? @"true" : @"false"]; [definitions appendFormat:@"- &h2_connection_keepalive_idle_interval %.*fs\n", 3, (double)self.h2ConnectionKeepaliveIdleIntervalMilliseconds / 1000.0]; [definitions appendFormat:@"- &h2_connection_keepalive_timeout %lus\n", diff --git a/library/objective-c/EnvoyEngine.h b/library/objective-c/EnvoyEngine.h index 0129cece17..9218ffc172 100644 --- a/library/objective-c/EnvoyEngine.h +++ b/library/objective-c/EnvoyEngine.h @@ -361,6 +361,7 @@ extern const int kEnvoyFilterResumeStatusResumeIteration; @property (nonatomic, assign) BOOL enableInterfaceBinding; @property (nonatomic, assign) BOOL enableDrainPostDnsRefresh; @property (nonatomic, assign) BOOL enforceTrustChainVerification; +@property (nonatomic, assign) BOOL forceIPv6; @property (nonatomic, assign) UInt32 h2ConnectionKeepaliveIdleIntervalMilliseconds; @property (nonatomic, assign) UInt32 h2ConnectionKeepaliveTimeoutSeconds; @property (nonatomic, assign) BOOL h2ExtendKeepaliveTimeout; @@ -397,6 +398,7 @@ extern const int kEnvoyFilterResumeStatusResumeIteration; enableInterfaceBinding:(BOOL)enableInterfaceBinding enableDrainPostDnsRefresh:(BOOL)enableDrainPostDnsRefresh enforceTrustChainVerification:(BOOL)enforceTrustChainVerification + forceIPv6:(BOOL)forceIPv6 h2ConnectionKeepaliveIdleIntervalMilliseconds: (UInt32)h2ConnectionKeepaliveIdleIntervalMilliseconds h2ConnectionKeepaliveTimeoutSeconds:(UInt32)h2ConnectionKeepaliveTimeoutSeconds diff --git a/library/swift/EngineBuilder.swift b/library/swift/EngineBuilder.swift index 56e91c8df2..726b01ac31 100644 --- a/library/swift/EngineBuilder.swift +++ b/library/swift/EngineBuilder.swift @@ -28,6 +28,7 @@ open class EngineBuilder: NSObject { private var enableInterfaceBinding: Bool = false private var enforceTrustChainVerification: Bool = true private var enableDrainPostDnsRefresh: Bool = false + private var forceIPv6: Bool = false private var h2ConnectionKeepaliveIdleIntervalMilliseconds: UInt32 = 1 private var h2ConnectionKeepaliveTimeoutSeconds: UInt32 = 10 private var h2ExtendKeepaliveTimeout: Bool = false @@ -228,6 +229,18 @@ open class EngineBuilder: NSObject { return self } + /// Specify whether to remap IPv4 addresses to the IPv6 space and always force connections + /// to use IPv6. Note this is an experimental option and should be enabled with caution. + /// + /// - parameter forceIPv6: whether to force connections to use IPv6. + /// + /// - returns: This builder. + @discardableResult + public func forceIPv6(_ forceIPv6: Bool) -> Self { + self.forceIPv6 = forceIPv6 + return self + } + /// Add a rate at which to ping h2 connections on new stream creation if the connection has /// sat idle. Defaults to 1 millisecond which effectively enables h2 ping functionality /// and results in a connection ping on every new stream creation. Set it to @@ -506,6 +519,7 @@ open class EngineBuilder: NSObject { enableInterfaceBinding: self.enableInterfaceBinding, enableDrainPostDnsRefresh: self.enableDrainPostDnsRefresh, enforceTrustChainVerification: self.enforceTrustChainVerification, + forceIPv6: self.forceIPv6, h2ConnectionKeepaliveIdleIntervalMilliseconds: self.h2ConnectionKeepaliveIdleIntervalMilliseconds, h2ConnectionKeepaliveTimeoutSeconds: self.h2ConnectionKeepaliveTimeoutSeconds, diff --git a/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt b/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt index 5da06cec76..27968982e4 100644 --- a/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt +++ b/test/java/io/envoyproxy/envoymobile/engine/EnvoyConfigurationTest.kt @@ -142,7 +142,7 @@ class EnvoyConfigurationTest { assertThat(resolvedTemplate).contains("&enable_interface_binding false") // Forcing IPv6 - assertThat(resolvedTemplate).contains("&android_force_ipv6 false") + assertThat(resolvedTemplate).contains("&force_ipv6 false") // H2 Ping assertThat(resolvedTemplate).contains("&h2_connection_keepalive_idle_interval 0.222s") @@ -227,7 +227,7 @@ class EnvoyConfigurationTest { assertThat(resolvedTemplate).contains("&enable_interface_binding true") // Forcing IPv6 - assertThat(resolvedTemplate).contains("&android_force_ipv6 true") + assertThat(resolvedTemplate).contains("&force_ipv6 true") } @Test diff --git a/test/swift/EngineBuilderTests.swift b/test/swift/EngineBuilderTests.swift index 6cf7cd5e27..a7ba6b0b2c 100644 --- a/test/swift/EngineBuilderTests.swift +++ b/test/swift/EngineBuilderTests.swift @@ -137,6 +137,20 @@ final class EngineBuilderTests: XCTestCase { self.waitForExpectations(timeout: 0.01) } + func testForceIPv6AddsToConfigurationWhenRunningEnvoy() { + let expectation = self.expectation(description: "Run called with force IPv6") + MockEnvoyEngine.onRunWithConfig = { config, _ in + XCTAssertTrue(config.forceIPv6) + expectation.fulfill() + } + + _ = EngineBuilder() + .addEngineType(MockEnvoyEngine.self) + .forceIPv6(true) + .build() + self.waitForExpectations(timeout: 0.01) + } + func testAddinggrpcStatsDomainAddsToConfigurationWhenRunningEnvoy() { let expectation = self.expectation(description: "Run called with expected data") MockEnvoyEngine.onRunWithConfig = { config, _ in @@ -471,6 +485,7 @@ final class EngineBuilderTests: XCTestCase { enableInterfaceBinding: true, enableDrainPostDnsRefresh: false, enforceTrustChainVerification: false, + forceIPv6: false, h2ConnectionKeepaliveIdleIntervalMilliseconds: 1, h2ConnectionKeepaliveTimeoutSeconds: 333, h2ExtendKeepaliveTimeout: true, @@ -558,6 +573,7 @@ final class EngineBuilderTests: XCTestCase { enableInterfaceBinding: false, enableDrainPostDnsRefresh: true, enforceTrustChainVerification: true, + forceIPv6: true, h2ConnectionKeepaliveIdleIntervalMilliseconds: 1, h2ConnectionKeepaliveTimeoutSeconds: 333, h2ExtendKeepaliveTimeout: false, @@ -610,6 +626,7 @@ final class EngineBuilderTests: XCTestCase { enableInterfaceBinding: false, enableDrainPostDnsRefresh: false, enforceTrustChainVerification: true, + forceIPv6: true, h2ConnectionKeepaliveIdleIntervalMilliseconds: 222, h2ConnectionKeepaliveTimeoutSeconds: 333, h2ExtendKeepaliveTimeout: false, diff --git a/test/swift/apps/experimental/ViewController.swift b/test/swift/apps/experimental/ViewController.swift index 59644895ed..2ab6603888 100644 --- a/test/swift/apps/experimental/ViewController.swift +++ b/test/swift/apps/experimental/ViewController.swift @@ -24,11 +24,19 @@ final class ViewController: UITableViewController { .addPlatformFilter(AsyncDemoFilter.init) .h2ExtendKeepaliveTimeout(true) .enableInterfaceBinding(true) - // swiftlint:disable:next line_length - .addNativeFilter(name: "envoy.filters.http.buffer", typedConfig: "{\"@type\":\"type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer\",\"max_request_bytes\":5242880}") + .addNativeFilter( + name: "envoy.filters.http.buffer", + typedConfig: """ + {\ + "@type":"type.googleapis.com/envoy.extensions.filters.http.buffer.v3.Buffer",\ + "max_request_bytes":5242880\ + } + """ + ) .setOnEngineRunning { NSLog("Envoy async internal setup completed") } .addStringAccessor(name: "demo-accessor", accessor: { return "PlatformString" }) .setEventTracker { NSLog("Envoy event emitted: \($0)") } + .forceIPv6(true) .build() self.streamClient = engine.streamClient() self.pulseClient = engine.pulseClient()