Created
January 29, 2019 21:10
-
-
Save ayende/434175a252bea84b02f374a5ff304c83 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
using System; | |
using System.IO; | |
using System.Net; | |
using System.Net.Security; | |
using System.Net.Sockets; | |
using System.Security.Cryptography.X509Certificates; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace TlsSpy | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
if (args.Length != 5) | |
{ | |
Console.WriteLine(@"TLS Spy Proxy usage: | |
tlspy.exe listen-port forward-host-and-port server-cert-path client-cert-path dir-name | |
"); | |
return; | |
} | |
if(int.TryParse(args[0], out var listenPort) == false) | |
{ | |
Console.WriteLine("Unable to parse listen port: " + args[0]); | |
return; | |
} | |
var forwardParts = args[1].Split(':'); | |
if(forwardParts.Length != 2) | |
{ | |
Console.WriteLine("Unable to parse forward host and port: " + args[1]); | |
return; | |
} | |
string forwardHost = forwardParts[0]; | |
if (int.TryParse(forwardParts[1], out var forwardPort) == false) | |
{ | |
Console.WriteLine("Unable to parse forward port: " + forwardParts[1]); | |
return; | |
} | |
X509Certificate2 serverCert, clientCert; | |
try | |
{ | |
serverCert = new X509Certificate2(args[2]); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine("Unable to open server cert: " + args[2]); | |
Console.WriteLine(e); | |
return; | |
} | |
try | |
{ | |
clientCert = new X509Certificate2(args[3]); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine("Unable to open client cert: " + args[3]); | |
Console.WriteLine(e); | |
return; | |
} | |
string outputDir; | |
try | |
{ | |
if(!Directory.Exists(args[4])) | |
Directory.CreateDirectory(args[4]); | |
outputDir = args[4]; | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine("Unable to create directory: " + args[4]); | |
Console.WriteLine(e); | |
return; | |
} | |
TcpListener tcpListener; | |
try | |
{ | |
tcpListener = new TcpListener(IPAddress.Any, listenPort); | |
tcpListener.Start(); | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine("Unable to listen to port: " + listenPort); | |
Console.WriteLine(e); | |
return; | |
} | |
} | |
private static int counter; | |
private static async Task ForwardAndClone(TcpClient client, string forwardHost, int forwardPort, X509Certificate2 serverCert, X509Certificate2 clientCert, string outputDir) | |
{ | |
var current = Interlocked.Increment(ref counter); | |
using (var output = File.Create(Path.Combine(outputDir, DateTime.Now.ToString("o") + "-" + current))) | |
using(var src = new SslStream(client.GetStream(), false, | |
(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true)) | |
{ | |
await src.AuthenticateAsServerAsync(serverCert); | |
using (var server = new TcpClient()) | |
{ | |
await server.ConnectAsync(forwardHost, forwardPort); | |
using (var dst = new SslStream(server.GetStream(), false, | |
(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) => true)) | |
{ | |
await dst.AuthenticateAsClientAsync(forwardHost, new X509CertificateCollection{ clientCert }, false); | |
var a = dst.CopyToAsync(src); | |
var b = src.CopyToAsync(dst); | |
await Task.WhenAll(a, b); | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment