Wire up the direct noise tunnel

This commit is contained in:
ravi-signal 2025-06-10 16:56:31 -05:00 committed by GitHub
parent 904cc63a72
commit 4ffd164461
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 39 additions and 24 deletions

View File

@ -491,7 +491,8 @@ linkDevice:
secret: secret://linkDevice.secret secret: secret://linkDevice.secret
noiseTunnel: noiseTunnel:
port: 8443 webSocketPort: 8444
directPort: 8445
tlsKeyStoreFile: /path/to/file.p12 tlsKeyStoreFile: /path/to/file.p12
tlsKeyStoreEntryAlias: example.com tlsKeyStoreEntryAlias: example.com
tlsKeyStorePassword: secret://noiseTunnel.tlsKeyStorePassword tlsKeyStorePassword: secret://noiseTunnel.tlsKeyStorePassword

View File

@ -43,7 +43,7 @@ import org.whispersystems.textsecuregcm.configuration.LinkDeviceSecretConfigurat
import org.whispersystems.textsecuregcm.configuration.MaxDeviceConfiguration; import org.whispersystems.textsecuregcm.configuration.MaxDeviceConfiguration;
import org.whispersystems.textsecuregcm.configuration.MessageByteLimitCardinalityEstimatorConfiguration; import org.whispersystems.textsecuregcm.configuration.MessageByteLimitCardinalityEstimatorConfiguration;
import org.whispersystems.textsecuregcm.configuration.MessageCacheConfiguration; import org.whispersystems.textsecuregcm.configuration.MessageCacheConfiguration;
import org.whispersystems.textsecuregcm.configuration.NoiseWebSocketTunnelConfiguration; import org.whispersystems.textsecuregcm.configuration.NoiseTunnelConfiguration;
import org.whispersystems.textsecuregcm.configuration.OneTimeDonationConfiguration; import org.whispersystems.textsecuregcm.configuration.OneTimeDonationConfiguration;
import org.whispersystems.textsecuregcm.configuration.PaymentsServiceConfiguration; import org.whispersystems.textsecuregcm.configuration.PaymentsServiceConfiguration;
import org.whispersystems.textsecuregcm.configuration.RegistrationServiceClientFactory; import org.whispersystems.textsecuregcm.configuration.RegistrationServiceClientFactory;
@ -304,7 +304,7 @@ public class WhisperServerConfiguration extends Configuration {
@Valid @Valid
@NotNull @NotNull
@JsonProperty @JsonProperty
private NoiseWebSocketTunnelConfiguration noiseTunnel; private NoiseTunnelConfiguration noiseTunnel;
@Valid @Valid
@NotNull @NotNull
@ -514,7 +514,7 @@ public class WhisperServerConfiguration extends Configuration {
return virtualThread; return virtualThread;
} }
public NoiseWebSocketTunnelConfiguration getNoiseWebSocketTunnelConfiguration() { public NoiseTunnelConfiguration getNoiseTunnelConfiguration() {
return noiseTunnel; return noiseTunnel;
} }

View File

@ -154,6 +154,7 @@ import org.whispersystems.textsecuregcm.grpc.net.GrpcClientConnectionManager;
import org.whispersystems.textsecuregcm.grpc.net.ManagedDefaultEventLoopGroup; import org.whispersystems.textsecuregcm.grpc.net.ManagedDefaultEventLoopGroup;
import org.whispersystems.textsecuregcm.grpc.net.ManagedLocalGrpcServer; import org.whispersystems.textsecuregcm.grpc.net.ManagedLocalGrpcServer;
import org.whispersystems.textsecuregcm.grpc.net.ManagedNioEventLoopGroup; import org.whispersystems.textsecuregcm.grpc.net.ManagedNioEventLoopGroup;
import org.whispersystems.textsecuregcm.grpc.net.noisedirect.NoiseDirectTunnelServer;
import org.whispersystems.textsecuregcm.grpc.net.websocket.NoiseWebSocketTunnelServer; import org.whispersystems.textsecuregcm.grpc.net.websocket.NoiseWebSocketTunnelServer;
import org.whispersystems.textsecuregcm.jetty.JettyHttpConfigurationCustomizer; import org.whispersystems.textsecuregcm.jetty.JettyHttpConfigurationCustomizer;
import org.whispersystems.textsecuregcm.keytransparency.KeyTransparencyServiceClient; import org.whispersystems.textsecuregcm.keytransparency.KeyTransparencyServiceClient;
@ -873,16 +874,17 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
@Nullable final X509Certificate[] noiseWebSocketTlsCertificateChain; @Nullable final X509Certificate[] noiseWebSocketTlsCertificateChain;
@Nullable final PrivateKey noiseWebSocketTlsPrivateKey; @Nullable final PrivateKey noiseWebSocketTlsPrivateKey;
if (config.getNoiseWebSocketTunnelConfiguration().tlsKeyStoreFile() != null && if (config.getNoiseTunnelConfiguration().tlsKeyStoreFile() != null &&
config.getNoiseWebSocketTunnelConfiguration().tlsKeyStoreEntryAlias() != null && config.getNoiseTunnelConfiguration().tlsKeyStoreEntryAlias() != null &&
config.getNoiseWebSocketTunnelConfiguration().tlsKeyStorePassword() != null) { config.getNoiseTunnelConfiguration().tlsKeyStorePassword() != null) {
try (final FileInputStream websocketNoiseTunnelTlsKeyStoreInputStream = new FileInputStream(config.getNoiseWebSocketTunnelConfiguration().tlsKeyStoreFile())) { try (final FileInputStream websocketNoiseTunnelTlsKeyStoreInputStream = new FileInputStream(config.getNoiseTunnelConfiguration().tlsKeyStoreFile())) {
final KeyStore keyStore = KeyStore.getInstance("PKCS12"); final KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(websocketNoiseTunnelTlsKeyStoreInputStream, config.getNoiseWebSocketTunnelConfiguration().tlsKeyStorePassword().value().toCharArray()); keyStore.load(websocketNoiseTunnelTlsKeyStoreInputStream, config.getNoiseTunnelConfiguration().tlsKeyStorePassword().value().toCharArray());
final KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(config.getNoiseWebSocketTunnelConfiguration().tlsKeyStoreEntryAlias(), final KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(
new KeyStore.PasswordProtection(config.getNoiseWebSocketTunnelConfiguration().tlsKeyStorePassword().value().toCharArray())); config.getNoiseTunnelConfiguration().tlsKeyStoreEntryAlias(),
new KeyStore.PasswordProtection(config.getNoiseTunnelConfiguration().tlsKeyStorePassword().value().toCharArray()));
noiseWebSocketTlsCertificateChain = noiseWebSocketTlsCertificateChain =
Arrays.copyOf(privateKeyEntry.getCertificateChain(), privateKeyEntry.getCertificateChain().length, X509Certificate[].class); Arrays.copyOf(privateKeyEntry.getCertificateChain(), privateKeyEntry.getCertificateChain().length, X509Certificate[].class);
@ -901,27 +903,37 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
.allowCoreThreadTimeOut(false) .allowCoreThreadTimeOut(false)
.build(); .build();
final ManagedNioEventLoopGroup noiseWebSocketEventLoopGroup = new ManagedNioEventLoopGroup(); final ManagedNioEventLoopGroup noiseTunnelEventLoopGroup = new ManagedNioEventLoopGroup();
final NoiseWebSocketTunnelServer noiseWebSocketTunnelServer = new NoiseWebSocketTunnelServer( final NoiseWebSocketTunnelServer noiseWebSocketTunnelServer = new NoiseWebSocketTunnelServer(
config.getNoiseWebSocketTunnelConfiguration().port(), config.getNoiseTunnelConfiguration().webSocketPort(),
noiseWebSocketTlsCertificateChain, noiseWebSocketTlsCertificateChain,
noiseWebSocketTlsPrivateKey, noiseWebSocketTlsPrivateKey,
noiseWebSocketEventLoopGroup, noiseTunnelEventLoopGroup,
noiseWebSocketDelegatedTaskExecutor, noiseWebSocketDelegatedTaskExecutor,
grpcClientConnectionManager, grpcClientConnectionManager,
clientPublicKeysManager, clientPublicKeysManager,
config.getNoiseWebSocketTunnelConfiguration().noiseStaticKeyPair(), config.getNoiseTunnelConfiguration().noiseStaticKeyPair(),
authenticatedGrpcServerAddress, authenticatedGrpcServerAddress,
anonymousGrpcServerAddress, anonymousGrpcServerAddress,
config.getNoiseWebSocketTunnelConfiguration().recognizedProxySecret().value()); config.getNoiseTunnelConfiguration().recognizedProxySecret().value());
final NoiseDirectTunnelServer noiseDirectTunnelServer = new NoiseDirectTunnelServer(
config.getNoiseTunnelConfiguration().directPort(),
noiseTunnelEventLoopGroup,
grpcClientConnectionManager,
clientPublicKeysManager,
config.getNoiseTunnelConfiguration().noiseStaticKeyPair(),
authenticatedGrpcServerAddress,
anonymousGrpcServerAddress);
environment.lifecycle().manage(localEventLoopGroup); environment.lifecycle().manage(localEventLoopGroup);
environment.lifecycle().manage(dnsResolutionEventLoopGroup); environment.lifecycle().manage(dnsResolutionEventLoopGroup);
environment.lifecycle().manage(anonymousGrpcServer); environment.lifecycle().manage(anonymousGrpcServer);
environment.lifecycle().manage(authenticatedGrpcServer); environment.lifecycle().manage(authenticatedGrpcServer);
environment.lifecycle().manage(noiseWebSocketEventLoopGroup); environment.lifecycle().manage(noiseTunnelEventLoopGroup);
environment.lifecycle().manage(noiseWebSocketTunnelServer); environment.lifecycle().manage(noiseWebSocketTunnelServer);
environment.lifecycle().manage(noiseDirectTunnelServer);
final List<Filter> filters = new ArrayList<>(); final List<Filter> filters = new ArrayList<>();
filters.add(remoteDeprecationFilter); filters.add(remoteDeprecationFilter);

View File

@ -10,12 +10,13 @@ import org.signal.libsignal.protocol.ecc.ECPrivateKey;
import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes; import org.whispersystems.textsecuregcm.configuration.secrets.SecretBytes;
import org.whispersystems.textsecuregcm.configuration.secrets.SecretString; import org.whispersystems.textsecuregcm.configuration.secrets.SecretString;
public record NoiseWebSocketTunnelConfiguration(@Positive int port, public record NoiseTunnelConfiguration(@Positive int webSocketPort,
@Nullable String tlsKeyStoreFile, @Positive int directPort,
@Nullable String tlsKeyStoreEntryAlias, @Nullable String tlsKeyStoreFile,
@Nullable SecretString tlsKeyStorePassword, @Nullable String tlsKeyStoreEntryAlias,
@NotNull SecretBytes noiseStaticPrivateKey, @Nullable SecretString tlsKeyStorePassword,
@NotNull SecretString recognizedProxySecret) { @NotNull SecretBytes noiseStaticPrivateKey,
@NotNull SecretString recognizedProxySecret) {
public ECKeyPair noiseStaticKeyPair() throws InvalidKeyException { public ECKeyPair noiseStaticKeyPair() throws InvalidKeyException {
final ECPrivateKey privateKey = Curve.decodePrivatePoint(noiseStaticPrivateKey().value()); final ECPrivateKey privateKey = Curve.decodePrivatePoint(noiseStaticPrivateKey().value());

View File

@ -485,7 +485,8 @@ linkDevice:
secret: secret://linkDevice.secret secret: secret://linkDevice.secret
noiseTunnel: noiseTunnel:
port: 8443 webSocketPort: 8444
directPort: 8445
noiseStaticPrivateKey: secret://noiseTunnel.noiseStaticPrivateKey noiseStaticPrivateKey: secret://noiseTunnel.noiseStaticPrivateKey
recognizedProxySecret: secret://noiseTunnel.recognizedProxySecret recognizedProxySecret: secret://noiseTunnel.recognizedProxySecret