mirror of
https://github.com/corda/corda.git
synced 2025-02-05 02:29:20 +00:00
Node can be configured to use an external relay for non-whitelisted inbound TCP connections.
It creates a SSH tunnel with the relay machine and forwards a remote port to the local message broker port.
This commit is contained in:
parent
782d4bd731
commit
cdb222cff2
@ -140,3 +140,14 @@ path to the node's base directory.
|
||||
|
||||
:certificateSigningService: Certificate Signing Server address. It is used by the certificate signing request utility to
|
||||
obtain SSL certificate. (See :doc:`permissioning` for more information.)
|
||||
|
||||
:relay: If provided, the node will attempt to tunnel inbound connections via an external relay. The relay's address will be
|
||||
advertised to the network map service instead of the provided ``p2pAddress``.
|
||||
|
||||
:relayHost: Hostname of the relay machine
|
||||
:remoteInboundPort: A port on the relay machine that accepts incoming TCP connections. Traffic will be forwarded
|
||||
from this port to the local port specified in ``p2pAddress``.
|
||||
:username: Username for establishing a SSH connection with the relay.
|
||||
:privateKeyFile: Path to the private key file for SSH authentication. The private key must not have a passphrase.
|
||||
:publicKeyFile: Path to the public key file for SSH authentication.
|
||||
:sshPort: Port to be used for SSH connection, default ``22``.
|
||||
|
@ -155,6 +155,9 @@ dependencies {
|
||||
// FastClasspathScanner: classpath scanning
|
||||
compile 'io.github.lukehutch:fast-classpath-scanner:2.0.20'
|
||||
|
||||
// Jsh: A SSH implementation for tunneling inbound traffic via a relay
|
||||
compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
|
||||
|
||||
// Integration test helpers
|
||||
integrationTestCompile "junit:junit:$junit_version"
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
package net.corda.node
|
||||
|
||||
import com.jcabi.manifests.Manifests
|
||||
import com.jcraft.jsch.JSch
|
||||
import com.jcraft.jsch.JSchException
|
||||
import com.typesafe.config.ConfigException
|
||||
import joptsimple.OptionException
|
||||
import net.corda.core.*
|
||||
@ -13,6 +15,7 @@ import net.corda.core.utilities.Emoji
|
||||
import net.corda.node.internal.Node
|
||||
import net.corda.node.internal.enforceSingleNodeIsRunning
|
||||
import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.node.services.config.RelayConfiguration
|
||||
import net.corda.node.services.transactions.bftSMaRtSerialFilter
|
||||
import net.corda.node.shell.InteractiveShell
|
||||
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
|
||||
@ -21,6 +24,7 @@ import org.fusesource.jansi.Ansi
|
||||
import org.fusesource.jansi.AnsiConsole
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.bridge.SLF4JBridgeHandler
|
||||
import java.io.IOException
|
||||
import java.lang.management.ManagementFactory
|
||||
import java.net.InetAddress
|
||||
import java.nio.file.Paths
|
||||
@ -104,7 +108,11 @@ fun main(args: Array<String>) {
|
||||
println("Unable to load the configuration file: ${e.rootCause.message}")
|
||||
exitProcess(2)
|
||||
}
|
||||
|
||||
SerialFilter.install(if (conf.bftReplicaId != null) ::bftSMaRtSerialFilter else ::defaultSerialFilter)
|
||||
|
||||
conf.relay?.let { connectToRelay(it, conf.p2pAddress.port) }
|
||||
|
||||
if (cmdlineOptions.isRegistration) {
|
||||
println()
|
||||
println("******************************************************************")
|
||||
@ -171,6 +179,37 @@ fun main(args: Array<String>) {
|
||||
exitProcess(0)
|
||||
}
|
||||
|
||||
private fun connectToRelay(config: RelayConfiguration, localBrokerPort: Int) {
|
||||
with(config) {
|
||||
val jsh = JSch().apply {
|
||||
val noPassphrase = byteArrayOf()
|
||||
addIdentity(privateKeyFile.toString(), publicKeyFile.toString(), noPassphrase)
|
||||
}
|
||||
|
||||
val session = jsh.getSession(username, relayHost, sshPort).apply {
|
||||
// We don't check the host fingerprints because they may change often
|
||||
setConfig("StrictHostKeyChecking", "no")
|
||||
}
|
||||
|
||||
try {
|
||||
log.info("Connecting to a relay at $relayHost")
|
||||
session.connect()
|
||||
} catch (e: JSchException) {
|
||||
throw IOException("Unable to establish a SSH connection: $username@$relayHost", e)
|
||||
}
|
||||
try {
|
||||
val localhost = "127.0.0.1"
|
||||
log.info("Forwarding ports: $relayHost:$remoteInboundPort -> $localhost:$localBrokerPort")
|
||||
session.setPortForwardingR(remoteInboundPort, localhost, localBrokerPort)
|
||||
} catch (e: JSchException) {
|
||||
throw IOException("Unable to set up port forwarding - is SSH on the remote host configured correctly? " +
|
||||
"(port forwarding is not enabled by default)", e)
|
||||
}
|
||||
}
|
||||
|
||||
log.info("Relay setup successfully!")
|
||||
}
|
||||
|
||||
private fun lookupMachineNameAndMaybeWarn(): String {
|
||||
val start = System.currentTimeMillis()
|
||||
val hostName: String = InetAddress.getLocalHost().hostName
|
||||
|
@ -58,6 +58,7 @@ data class FullNodeConfiguration(
|
||||
@OldConfig("artemisAddress")
|
||||
val p2pAddress: HostAndPort,
|
||||
val rpcAddress: HostAndPort?,
|
||||
val relay: RelayConfiguration?,
|
||||
// TODO This field is slightly redundant as p2pAddress is sufficient to hold the address of the node's MQ broker.
|
||||
// Instead this should be a Boolean indicating whether that broker is an internal one started by the node or an external one
|
||||
val messagingServerAddress: HostAndPort?,
|
||||
@ -116,3 +117,10 @@ data class CertChainPolicyConfig(val role: String, val policy: CertChainPolicyTy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class RelayConfiguration(val relayHost: String,
|
||||
val remoteInboundPort: Int,
|
||||
val username: String,
|
||||
val privateKeyFile: Path,
|
||||
val publicKeyFile: Path,
|
||||
val sshPort: Int = 22)
|
@ -193,7 +193,8 @@ fun testConfiguration(baseDirectory: Path, legalName: X500Name, basePort: Int):
|
||||
notaryNodeAddress = null,
|
||||
notaryClusterAddresses = emptyList(),
|
||||
certificateChainCheckPolicies = emptyList(),
|
||||
devMode = true)
|
||||
devMode = true,
|
||||
relay = null)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
|
Loading…
x
Reference in New Issue
Block a user