diff --git a/node/src/main/resources/application.conf b/node/src/main/resources/application.conf index 5d88fb2..f465767 100644 --- a/node/src/main/resources/application.conf +++ b/node/src/main/resources/application.conf @@ -57,6 +57,9 @@ acryl { # Docker machine host / IP address (used in the integration tests) docker-ip-address = "localhost" + # SOCKS5 proxy + # proxy = "127.0.0.1:9050" + # List of IP addresses of well known nodes. known-peers = ["188.166.74.161:6870", "159.203.115.46:6870", "206.189.155.110:6870", "134.209.201.198:6870"] diff --git a/node/src/main/scala/com/acrylplatform/Application.scala b/node/src/main/scala/com/acrylplatform/Application.scala index bf02c60..199c3fb 100644 --- a/node/src/main/scala/com/acrylplatform/Application.scala +++ b/node/src/main/scala/com/acrylplatform/Application.scala @@ -326,7 +326,10 @@ class Application(val actorSystem: ActorSystem, val settings: AcrylSettings, con val httpFuture = SSLConnection.getSSL(settings.restAPISettings) match { case Left(message) => log.debug(message) - Http2().bindAndHandleAsync(asyncHandler, settings.restAPISettings.bindAddress, settings.restAPISettings.port, ConnectionContext.noEncryption()) + Http2().bindAndHandleAsync(asyncHandler, + settings.restAPISettings.bindAddress, + settings.restAPISettings.port, + ConnectionContext.noEncryption()) case Right(https) => log.debug("HTTPS enable") Http().bindAndHandleAsync(asyncHandler, settings.restAPISettings.bindAddress, settings.restAPISettings.port, https) diff --git a/node/src/main/scala/com/acrylplatform/network/NetworkServer.scala b/node/src/main/scala/com/acrylplatform/network/NetworkServer.scala index 0781943..59b4df4 100644 --- a/node/src/main/scala/com/acrylplatform/network/NetworkServer.scala +++ b/node/src/main/scala/com/acrylplatform/network/NetworkServer.scala @@ -19,6 +19,7 @@ import io.netty.channel.nio.NioEventLoopGroup import io.netty.channel.socket.SocketChannel import io.netty.channel.socket.nio.{NioServerSocketChannel, NioSocketChannel} import io.netty.handler.codec.{LengthFieldBasedFrameDecoder, LengthFieldPrepender} +import io.netty.handler.proxy.Socks5ProxyHandler import io.netty.util.concurrent.DefaultThreadFactory import monix.reactive.Observable import org.influxdb.dto.Point @@ -136,25 +137,33 @@ object NetworkServer extends ScorexLogging { .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, settings.networkSettings.connectionTimeout.toMillis.toInt: Integer) .group(workerGroup) .channel(classOf[NioSocketChannel]) - .handler(new PipelineInitializer[SocketChannel](Seq( - new BrokenConnectionDetector(settings.networkSettings.breakIdleConnectionsTimeout), - new HandshakeDecoder(peerDatabase), - new HandshakeTimeoutHandler(settings.networkSettings.handshakeTimeout), - clientHandshakeHandler, - lengthFieldPrepender, - new LengthFieldBasedFrameDecoder(100 * 1024 * 1024, 0, 4, 0, 4), - new LegacyFrameCodec(peerDatabase, settings.networkSettings.receivedTxsCacheTimeout), - channelClosedHandler, - trafficWatcher, - discardingHandler, - messageCodec, - trafficLogger, - writeErrorHandler, - peerSynchronizer, - historyReplier, - messageObserver, - fatalErrorHandler - ))) + .handler(new ChannelInitializer[Channel] { + override def initChannel(ch: Channel): Unit = { + val pipeline = ch.pipeline() + pipeline.addLast(new BrokenConnectionDetector(settings.networkSettings.breakIdleConnectionsTimeout)) + pipeline.addLast(new HandshakeDecoder(peerDatabase)) + pipeline.addLast(new HandshakeTimeoutHandler(settings.networkSettings.handshakeTimeout)) + pipeline.addLast(clientHandshakeHandler) + pipeline.addLast(lengthFieldPrepender) + pipeline.addLast(new LengthFieldBasedFrameDecoder(100 * 1024 * 1024, 0, 4, 0, 4)) + pipeline.addLast(new LegacyFrameCodec(peerDatabase, settings.networkSettings.receivedTxsCacheTimeout)) + pipeline.addLast(channelClosedHandler) + pipeline.addLast(trafficWatcher) + pipeline.addLast(discardingHandler) + pipeline.addLast(messageCodec) + pipeline.addLast(trafficLogger) + pipeline.addLast(writeErrorHandler) + pipeline.addLast(peerSynchronizer) + pipeline.addLast(historyReplier) + pipeline.addLast(messageObserver) + pipeline.addLast(fatalErrorHandler) + + settings.networkSettings.proxy match { + case Some(value) => pipeline.addFirst(new Socks5ProxyHandler(value)) + case None => + } + } + }) def formatOutgoingChannelEvent(channel: Channel, event: String) = s"${id(channel)} $event, outgoing channel count: ${outgoingChannels.size()}" diff --git a/node/src/main/scala/com/acrylplatform/settings/NetworkSettings.scala b/node/src/main/scala/com/acrylplatform/settings/NetworkSettings.scala index 160eaa2..e0db5f9 100644 --- a/node/src/main/scala/com/acrylplatform/settings/NetworkSettings.scala +++ b/node/src/main/scala/com/acrylplatform/settings/NetworkSettings.scala @@ -19,6 +19,7 @@ case class NetworkSettings(file: Option[File], bindAddress: InetSocketAddress, declaredAddress: Option[InetSocketAddress], dockerIpAddress: String, + proxy: Option[InetSocketAddress], nodeName: String, nonce: Long, knownPeers: Seq[String], @@ -64,6 +65,11 @@ object NetworkSettings { new InetSocketAddress(uri.getHost, uri.getPort) } + val proxy = config.getAs[String]("proxy").map { address => + val uri = new URI(s"my://$address") + new InetSocketAddress(uri.getHost, uri.getPort) + } + val dockerIpAddress = config.as[String]("docker-ip-address") val knownPeers = config.as[Seq[String]]("known-peers") val savingPeers = config.as[Boolean]("saving-peers") @@ -89,6 +95,7 @@ object NetworkSettings { bindAddress, declaredAddress, dockerIpAddress, + proxy, nodeName, nonce, knownPeers, diff --git a/project/Dependencies.scala b/project/Dependencies.scala index f2e92d2..1d4404c 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -152,6 +152,7 @@ object Dependencies { kindProjector, monixModule("reactive").value, nettyModule("handler"), + nettyModule("handler-proxy"), akkaModule("testkit") % Test, akkaHttpModule("akka-http-testkit") % Test, ("org.iq80.leveldb" % "leveldb" % "0.12").exclude("com.google.guava", "guava") % Test