2using System.Collections.Generic;
3using System.Security.Cryptography;
4using System.Security.Cryptography.X509Certificates;
5using System.Threading.Tasks;
20 private int listeningPort = 0;
21 private string remoteIpsExpression =
string.Empty;
22 private string proxyKey =
null;
23 private bool trustServer =
false;
24 private bool authorizedAccess =
false;
25 private IpCidr[] remoteIps =
null;
34 return Task.FromResult(
false);
51 [Header(28,
"Trust Server", 80)]
52 [ToolTip(29,
"Check if Server Certificate should be trusted.")]
55 get => this.trustServer;
56 set => this.trustServer = value;
63 [Header(25,
"Listening Port Number:", 90)]
64 [ToolTip(26,
"Port number to listen on for incoming conncetions.")]
69 get => this.listeningPort;
70 set => this.listeningPort = value;
76 [Page(33,
"Security")]
77 [Header(34,
"Authorized Access Only (mTLS)", 80)]
78 [ToolTip(35,
"If checked, mTLS will be used, requiring connecting clients to provide a client certificate authorizing access to port.")]
82 get => this.authorizedAccess;
83 set => this.authorizedAccess = value;
90 [Page(33,
"Security")]
91 [Header(36,
"Restrict to Remote IPs", 80)]
92 [ToolTip(37,
"IP Addresses are specified using a comma-delimited list of IP Addresses or IP CIDR ranges.")]
93 [RegularExpression(
@"\s*\d+\.\d+\.\d+\.\d+(\/\d+)?(\s*,\s*\d+\.\d+\.\d+\.\d+(\/\d+)?)*")]
94 [DefaultValueStringEmpty]
97 get => this.remoteIpsExpression;
100 if (
string.IsNullOrEmpty(value))
101 this.remoteIps =
null;
104 List<IpCidr> Ranges =
new List<IpCidr>();
105 string[] Parts = value.Split(
new char[] {
',' }, StringSplitOptions.RemoveEmptyEntries);
107 foreach (
string Part
in Parts)
110 throw new Exception(
"Invalid IP Address or CIDR specification.");
115 if (Ranges.Count == 0)
116 this.remoteIps =
null;
118 this.remoteIps = Ranges.ToArray();
121 this.remoteIpsExpression = value;
133 LinkedList<Parameter> Result = await base.GetDisplayableParametersAsync(
Language, Caller) as LinkedList<Parameter>;
151 if (!
string.IsNullOrEmpty(this.proxyKey))
154 return base.DestroyAsync();
165 string PrevKey = this.proxyKey;
166 this.proxyKey =
ProxyPorts.
GetKey(this.
Host, this.
Port, this.
Tls, this.trustServer, this.listeningPort, this.authorizedAccess, this.remoteIps);
168 if (PrevKey != this.proxyKey && !
string.IsNullOrEmpty(PrevKey))
171 return this.proxyKey;
180 await this.GetProxy();
181 await base.NodeUpdated();
184 internal Task<ProxyPort> GetProxy()
196 List<string> Domains =
new List<string>();
197 bool HasAlternativeNames =
false;
199 foreach (
string Part
in Certificate.Subject.Split(certificateSubjectSeparator, StringSplitOptions.None))
201 if (Part.StartsWith(
"CN="))
202 Domains.Add(Part.Substring(3));
203 else if (Part.StartsWith(
"SAN="))
205 Domains.Add(Part.Substring(4));
206 HasAlternativeNames =
true;
210 if (!HasAlternativeNames)
212 if (!(Certificate is X509Certificate2 Cert2))
214 byte[] Bin = Certificate.GetRawCertData();
215 Cert2 =
new X509Certificate2(Bin);
218 foreach (X509Extension Extension
in Cert2.Extensions)
220 if (Extension.Oid.Value ==
"2.5.29.17")
222 AsnEncodedData Parsed =
new AsnEncodedData(Extension.Oid, Extension.RawData);
223 string[] SAN = Parsed.Format(
true).Split(
CommonTypes.
CRLF, StringSplitOptions.RemoveEmptyEntries);
225 foreach (
string Name in SAN)
227 int i =
Name.LastIndexOf(
'=');
229 Domains.Add(
Name.Substring(i + 1));
235 return Domains.ToArray();
238 private readonly
static string[] certificateSubjectSeparator =
new string[] {
", " };
Helps with parsing of commong data types.
static readonly char[] CRLF
Contains the CR LF character sequence.
Contains information about a language.
Task< string > GetStringAsync(Type Type, int Id, string Default)
Gets the string value of a string ID. If no such string exists, a string is created with the default ...
IP Address Rangee, expressed using CIDR format.
static bool TryParse(string s, out IpCidr Parsed)
Tries to parse an IP Range in CIDR format. (An IP Address alone is considered implicitly having a mas...
Node representing an IP Host machine.
string Host
Host name or IP address.
Node representing a port on an IP Host machine.
bool Tls
If connection is encrypted using TLS or not.
Node representing a proxy port node.
bool TrustServer
If connection is encrypted using TLS or not.
bool AuthorizedAccess
If connection is encrypted using TLS or not.
string Key
Key identifying node.
override Task DestroyAsync()
Destroys the node. If it is a child to a parent node, it is removed from the parent first.
override async Task NodeUpdated()
Persists changes to the node, and generates a node updated event.
override Task< string > GetTypeNameAsync(Language Language)
Gets the type name of the node.
async override Task< IEnumerable< Parameter > > GetDisplayableParametersAsync(Language Language, RequestOrigin Caller)
Gets displayable parameters.
override Task< bool > AcceptsChildAsync(INode Child)
If the node accepts a presumptive child, i.e. can receive as a child (if that child accepts the node ...
string RemoteIps
If connections should be restricted to the Remote IPs defined by this expression. IP Addresses are sp...
static string[] GetCertificateIdentities(X509Certificate Certificate)
Gets names (subject and alternative) encoded in a certificate.
int ListeningPort
Incoming Port number.
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
int NrConnctions
Number of connections.
long NrBytesDownlink
Number of bytes send downlink
Static class managing Port Proxies.
static async Task< ProxyPort > GetProxy(IpHostPortProxy Node, string Key, string Host, int Port, bool Tls, bool TrustServer, int ListeningPort, bool AuthorizedAccess, IpCidr[] RemoteIps)
Gets a TCP/IP proxy node
static void DestroyProxy(string Key)
Destroys a proxy node
static string GetKey(string Host, int Port, bool Tls, bool TrustServer, int ListeningPort, bool AuthorizedAccess, IpCidr[] RemoteIps)
Gets sort key for Port Proxy
Tokens available in request.
Interface for nodes that are published through the concentrator interface.