-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
146 additions
and
191 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,30 @@ | ||
package com.karasiq.proxychain.app | ||
|
||
import java.io.IOException | ||
import java.net.InetSocketAddress | ||
import java.nio.channels.{ServerSocketChannel, SocketChannel} | ||
import java.util.concurrent.Executors | ||
|
||
import akka.actor._ | ||
import akka.event.Logging | ||
import com.karasiq.proxychain.AppConfig | ||
import com.karasiq.tls.TLSServerWrapper | ||
import org.apache.commons.io.IOUtils | ||
|
||
import scala.concurrent.{ExecutionContext, Future, Promise} | ||
import scala.util.{Failure, Success, control} | ||
import scala.language.postfixOps | ||
|
||
private[app] object Server { | ||
def props(cfg: AppConfig, tls: Boolean = false): Props = { | ||
Props(classOf[Server], cfg, tls) | ||
} | ||
} | ||
|
||
class Server(cfg: AppConfig) extends Actor with ActorLogging { | ||
private[app] class Server(cfg: AppConfig, tls: Boolean) extends Actor with ActorLogging { | ||
import akka.io.Tcp._ | ||
|
||
def receive = { | ||
case Bound(address) ⇒ | ||
log.info("Proxy server running on {}", address) | ||
log.info("{} server running on {}", if (tls) "TLS-Proxy" else "Proxy", address) | ||
|
||
case CommandFailed(_: Bind) ⇒ | ||
context.stop(self) | ||
|
||
case c @ Connected(remote, local) ⇒ // New connection accepted | ||
val handler = context.actorOf(Props(classOf[Handler], cfg, remote)) | ||
val connection = sender() | ||
val handler = context.actorOf(Props(if (tls) classOf[TLSHandler] else classOf[Handler], connection, cfg, remote)) | ||
connection ! Register(handler) | ||
} | ||
} | ||
|
||
// TLS tamper | ||
class TLSServer(address: InetSocketAddress, cfg: AppConfig) extends Actor with ActorLogging { | ||
import akka.io.Tcp._ | ||
val serverSocket = ServerSocketChannel.open() | ||
private case class Accepted(socket: SocketChannel) | ||
|
||
private val tlsConfig = AppConfig.tlsConfig() | ||
|
||
private val acceptor = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor()) | ||
|
||
@throws[Exception](classOf[Exception]) | ||
override def preStart(): Unit = { | ||
super.preStart() | ||
serverSocket.bind(address) | ||
acceptor.execute(new Runnable { | ||
override def run(): Unit = { | ||
control.Exception.ignoring(classOf[IOException]) { | ||
while (serverSocket.isOpen) { | ||
self ! Accepted(serverSocket.accept()) | ||
} | ||
} | ||
} | ||
}) | ||
log.info("TLS-proxy server running on {}", address) | ||
} | ||
|
||
|
||
@throws[Exception](classOf[Exception]) | ||
override def postStop(): Unit = { | ||
super.postStop() | ||
IOUtils.closeQuietly(serverSocket) | ||
acceptor.shutdown() | ||
} | ||
|
||
def receive = { | ||
case Accepted(socket) ⇒ // New connection accepted | ||
import context.dispatcher | ||
val handler = context.actorOf(Props(classOf[Handler], cfg, socket.getRemoteAddress.asInstanceOf[InetSocketAddress])) | ||
val catcher = control.Exception.allCatch.withApply { exc ⇒ | ||
context.stop(handler) | ||
IOUtils.closeQuietly(socket) | ||
} | ||
|
||
catcher { | ||
val log = Logging(context.system, handler) | ||
|
||
val tlsSocket = Promise[SocketChannel]() | ||
tlsSocket.future.onComplete { | ||
case Success(sc) ⇒ | ||
log.debug("TLS handshake finished") | ||
val actor = context.actorOf(Props(classOf[TLSHandlerTamper], sc)) | ||
actor ! Register(handler) | ||
|
||
case Failure(exc) ⇒ | ||
log.error(exc, "Error opening TLS socket") | ||
handler ! ErrorClosed | ||
IOUtils.closeQuietly(socket) | ||
} | ||
|
||
val serverWrapper = new TLSServerWrapper(tlsConfig.keySet, tlsConfig.clientAuth, tlsConfig.verifier) { | ||
override protected def onInfo(message: String): Unit = { | ||
log.debug(message) | ||
} | ||
|
||
override protected def onError(message: String, exc: Throwable): Unit = { | ||
log.error(exc, message) | ||
} | ||
} | ||
|
||
tlsSocket.completeWith(Future { | ||
serverWrapper(socket) | ||
}) | ||
} | ||
} | ||
} |
Oops, something went wrong.