3using System.ComponentModel;
6using System.Net.NetworkInformation;
8using System.Security.Authentication;
9using System.Security.Cryptography.X509Certificates;
11using System.Threading.Tasks;
28 private readonly LinkedList<TcpListener> tcpListeners =
new LinkedList<TcpListener>();
29 private readonly Dictionary<Guid, ProxyClientConncetion> connections =
new Dictionary<Guid, ProxyClientConncetion>();
30 private readonly
IpCidr[] remoteIps;
32 private readonly
string host;
33 private readonly
int port;
34 private readonly
int listeningPort;
35 private readonly
bool tls;
36 private readonly
bool trustServer;
37 private readonly
bool authorizedAccess;
38 private long nrBytesDownlink = 0;
39 private long nrBytesUplink = 0;
40 private bool closed =
false;
42 private ProxyPort(
IpHostPortProxy Node,
string Host,
int Port,
bool Tls,
bool TrustServer,
int ListeningPort,
bool AuthorizedAccess,
50 this.trustServer = TrustServer;
51 this.listeningPort = ListeningPort;
52 this.authorizedAccess = AuthorizedAccess;
53 this.remoteIps = RemoteIps;
68 public static async Task<ProxyPort>
Create(
IpHostPortProxy Node,
string Host,
int Port,
bool Tls,
bool TrustServer,
int ListeningPort,
69 bool AuthorizedAccess,
IpCidr[] RemoteIps)
71 ProxyPort Result =
new ProxyPort(Node, Host, Port, Tls, TrustServer, ListeningPort, AuthorizedAccess, RemoteIps);
76 private async Task Open()
78 foreach (NetworkInterface Interface
in NetworkInterface.GetAllNetworkInterfaces())
80 if (Interface.OperationalStatus != OperationalStatus.Up)
83 IPInterfaceProperties Properties = Interface.GetIPProperties();
85 foreach (UnicastIPAddressInformation UnicastAddress
in Properties.UnicastAddresses)
87 if ((UnicastAddress.Address.AddressFamily == AddressFamily.InterNetwork && Socket.OSSupportsIPv4) ||
88 (UnicastAddress.Address.AddressFamily == AddressFamily.InterNetworkV6 && Socket.OSSupportsIPv6))
90 IPEndPoint DesiredEndpoint =
new IPEndPoint(UnicastAddress.Address,
this.listeningPort);
94 TcpListener Listener =
new TcpListener(UnicastAddress.Address,
this.listeningPort);
97 Task T = this.ListenForIncomingConnections(Listener);
99 lock (this.tcpListeners)
101 this.tcpListeners.AddLast(Listener);
104 await this.node.RemoveErrorAsync(DesiredEndpoint.ToString());
106 catch (SocketException)
108 await this.node.LogErrorAsync(DesiredEndpoint.ToString(),
"Unable to open Proxy port for listening.");
112 await this.node.LogErrorAsync(DesiredEndpoint.ToString(), ex.Message);
119 private async Task ListenForIncomingConnections(TcpListener Listener)
131 Client = await Listener.AcceptTcpClientAsync();
135 catch (InvalidOperationException)
137 lock (this.tcpListeners)
139 LinkedListNode<TcpListener> Node = this.tcpListeners?.First;
141 while (!(Node is
null))
143 if (Node.Value == Listener)
145 this.tcpListeners.Remove(Node);
156 if (!(Client is
null))
158 if (!(this.remoteIps is
null))
162 if (Client.Client.RemoteEndPoint is IPEndPoint IPEndPoint)
164 foreach (
IpCidr Range
in this.remoteIps)
166 if (Range.
Matches(IPEndPoint.Address))
176 this.
Error(
"Remote IP not approved. Conncetion reused.");
194 if (!await Outgoing.
ConnectAsync(
this.host,
this.port,
true))
196 await this.node.LogErrorAsync(
"UnableToConnect",
"Unable to connect to remote endpoint.");
206 await this.node.LogErrorAsync(
"UnableToConnect",
"Unable to connect to remote endpoint: " + ex.Message);
210 if (!(Outgoing is
null))
216 await this.node.RemoveErrorAsync(
"UnableToConnect");
218 if ((this.tls || this.authorizedAccess) && !(Certificate is
null))
220 await this.node.RemoveWarningAsync(
"NoCertificate");
222 Task
_ = this.SwitchToTls(Incoming, Outgoing, Certificate);
227 await this.node.LogWarningAsync(
"NoCertificate",
"No registered certificate found. Listening port is unencrypted.");
229 ProxyClientConncetion Connection =
new ProxyClientConncetion(
this, Incoming, Outgoing, this.Sniffers);
233 lock (this.connections)
235 this.connections[Connection.Id] = Connection;
240 catch (SocketException)
244 catch (ObjectDisposedException)
248 catch (NullReferenceException)
254 if (this.closed || this.tcpListeners is
null)
259 foreach (TcpListener P
in this.tcpListeners)
277 if (this.closed || this.tcpListeners is
null)
296 if (this.authorizedAccess)
300 this.
Error(
"No remote certificate found. mTLS is required.");
308 this.
Error(
"Remote certificate not valid.");
314 string[] Identities = IpHostPortProxy.GetCertificateIdentities(Incoming.
RemoteCertificate);
317 foreach (
string Identity
in IpHostPortProxy.GetCertificateIdentities(Certificate))
324 string RemoteEndPoint = Incoming.
RemoteEndPoint.RemovePortNumber();
328 string Msg =
"Invalid login: No user found matching certificate subject.";
343 ", Hash Strength: " + Incoming.
HashStrength.ToString() +
350 StringBuilder sb =
new StringBuilder();
352 sb.Append(
"Remote Certificate received. Valid: ");
354 sb.Append(
", Subject: ");
356 sb.Append(
", Issuer: ");
358 sb.Append(
", S/N: ");
360 sb.Append(
", Hash: ");
368 ProxyClientConncetion Connection =
new ProxyClientConncetion(
this, Incoming, Outgoing, this.Sniffers);
372 lock (this.connections)
374 this.connections[Connection.Id] = Connection;
377 catch (AuthenticationException ex)
381 catch (Win32Exception ex)
383 if (ex is SocketException)
421 TcpListener[] Listeners;
422 ProxyClientConncetion[] Connections;
426 lock (this.tcpListeners)
428 Listeners =
new TcpListener[this.tcpListeners.Count];
429 this.tcpListeners.CopyTo(Listeners, 0);
430 this.tcpListeners.Clear();
433 lock (this.connections)
435 Connections =
new ProxyClientConncetion[this.connections.Count];
436 this.connections.Values.CopyTo(Connections, 0);
437 this.connections.Clear();
440 foreach (TcpListener Listener
in Listeners)
452 foreach (ProxyClientConncetion Connection
in Connections)
456 Connection.Dispose();
479 lock (this.connections)
481 this.connections.Remove(Connection.
Id);
493 this.nrBytesUplink += NrBytes;
502 this.nrBytesDownlink += NrBytes;
522 lock (this.connections)
524 return this.connections.Count;
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Implements a binary TCP Client, by encapsulating a TcpClient. It also makes the use of TcpClient safe...
void Bind()
Binds to a TcpClient that was already connected when provided to the constructor.
Task UpgradeToTlsAsClient(SslProtocols Protocols)
Upgrades a client connection to TLS.
bool RemoteCertificateValid
If the remote certificate is valid.
int HashStrength
Hash algorithm strength. (Nr bits of brute force complexity required to break algorithm).
string RemoteEndPoint
Remote End-point of connection. This corresponds to the IP Endpoint of the remote party in normal cas...
void DisposeWhenDone()
Disposes the client when done sending all data.
void Continue()
Continues reading from the socket, if paused in an event handler.
virtual Task DisposeAsync()
Disposes of the object asynchronously. The underlying TcpClient is either disposed directly,...
X509Certificate RemoteCertificate
Certificate used by the remote endpoint.
int KeyExchangeStrength
Key Exchange strength. (Nr bits of brute force complexity required to break algorithm).
int CipherStrength
Cipher strength. (Nr bits of brute force complexity required to break algorithm).
Task< bool > ConnectAsync(string Host, int Port)
Connects to a host using TCP.
Task UpgradeToTlsAsServer(X509Certificate ServerCertificate)
Upgrades a server connection to TLS.
Simple base class for classes implementing communication protocols.
void Exception(Exception Exception)
Called to inform the viewer of an exception state.
ISniffer[] Sniffers
Registered sniffers.
bool HasSniffers
If there are sniffers registered on the object.
void Error(string Error)
Called to inform the viewer of an error state.
void Information(string Comment)
Called to inform the viewer of something.
IP Address Rangee, expressed using CIDR format.
bool Matches(string Endpoint)
Checks if an IP Address matches the defined range.
Static class that dynamically manages types and interfaces available in the runtime environment.
static bool TryGetModuleParameter(string Name, out object Value)
Tries to get a module parameter value.
Helper methods for encrypting and decrypting streams of data.
const SslProtocols SecureTls
TLS 1.2 & 1.3
const SslProtocols TlsOnly
TLS 1.0, 1.1, 1.2 & 1.3
Class that monitors login events, and help applications determine malicious intent....
static async void Success(string Message, string UserName, string RemoteEndPoint, string Protocol, params KeyValuePair< string, object >[] Tags)
Handles a successful login attempt.
static bool CanStartTls(string RemoteEndPoint)
Checks if TLS negotiation can start, for a given endpoint. If the endpoint has tries a TLS hack attem...
static void ReportTlsHackAttempt(string RemoteEndPoint, string Message, string Protocol)
Reports a TLS hacking attempt from an endpoint. Can be used to deny TLS negotiation to proceed,...
static void Fail(string Message, string UserName, string RemoteEndPoint, string Protocol)
Handles a failed login attempt.
Login state information relating to a remote endpoint
Corresponds to a user in the system.
Maintains the collection of all users in the system.
static async Task< User > GetUser(string UserName, bool CreateIfNew)
Gets the User object corresponding to a User Name.
Node representing a proxy port node.
Maintains one proxy connection
void Dispose()
IDisposable.Dispose
Node acting as a TCP/IP proxy opening a port for incoming communication and proxying it to another po...
long NrBytesUplink
Number of bytes send uplink
void IncDownlink(int NrBytes)
Increment downlink counter.
void Remove(ProxyClientConncetion Connection)
Removes a proxy client connection.
int NrConnctions
Number of connections.
long NrBytesDownlink
Number of bytes send downlink
void Dispose()
IDisposable.Dispose
static async Task< ProxyPort > Create(IpHostPortProxy Node, string Host, int Port, bool Tls, bool TrustServer, int ListeningPort, bool AuthorizedAccess, IpCidr[] RemoteIps)
Creates a port proxy object.
void IncUplink(int NrBytes)
Increment uplink counter.
Interface for sniffers. Sniffers can be added to ICommunicationLayer classes to eavesdrop on communic...
ClientCertificates
Client Certificate Options