feat: 实现端口代理工具的核心功能

This commit is contained in:
2025-01-28 22:57:40 +08:00
parent 6f373dc5e5
commit 3e231fcc8c
3 changed files with 169 additions and 0 deletions

150
PortProxyTool/PortProxy.cs Normal file
View File

@@ -0,0 +1,150 @@
using System.Diagnostics;
using System.Text;
namespace PortProxyTool;
public static class PortProxy
{
public static PortProxyItem[] GetPortProxies()
{
var output = ExecuteCommand("show all");
var lines = output.ToList();
var items = new List<PortProxyItem>();
if (output.Length <= 0) return items.ToArray();
PortProxyType? currentType = null;
for (var i = 0; i < lines.Count; i++)
{
var line = lines[i];
var type = CheckPosition(line);
if (type != null)
{
currentType = type.Value;
if (i + 1 >= lines.Count) continue;
lines.RemoveAt(i + 1);
lines.RemoveAt(i + 1);
}
else if (currentType != null)
{
var values = line.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (values.Length < 2) continue;
var listenAddress = values[0];
if (!ushort.TryParse(values[1], out var listenPort))
{
Remove(type, listenAddress, values[1]);
continue;
}
string? targetAddress = null;
ushort? targetPort = null;
if (values.Length >= 4)
{
targetAddress = values[2];
if (!ushort.TryParse(values[3], out var targetPortParse))
targetPort = null;
else
targetPort = targetPortParse;
}
items.Add(new PortProxyItem
{
Type = currentType.Value,
ListenAddress = listenAddress,
ListenPort = listenPort,
TargetAddress = targetAddress,
TargetPort = targetPort
});
}
}
return items.ToArray();
}
public static string Remove(PortProxyType? type, string listenAddress, string listenPort, string protocol = "tcp")
{
var output =
ExecuteCommand(
$"delete {type?.ToString().ToLower()} listenaddress=\"{listenAddress}\" listenport=\"{listenPort}\" protocol=\"{protocol}\"");
return output.Length > 0 ? output[0] : string.Empty;
}
public static string Remove(PortProxyItem item)
{
return Remove(item.Type, item.ListenAddress, item.ListenPort.ToString());
}
public static string Add(PortProxyType type, string listenAddress, ushort listenPort, string connectAddress, ushort connectPort, string protocol = "tcp")
{
var output =
ExecuteCommand(
$"delete {type.ToString().ToLower()} listenaddress=\"{listenAddress}\" listenport=\"{listenPort}\" connectAddress=\"{connectAddress}\" connectPort=\"{connectPort}\" protocol=\"{protocol}\"");
return output.Length > 0 ? output[0] : string.Empty;
}
public static string Add(PortProxyItem item)
{
return Add(item.Type, item.ListenAddress, item.ListenPort, item.TargetAddress!, item.TargetPort ?? 0);
}
public static string Set(PortProxyType type, string listenAddress, ushort listenPort, string connectAddress, ushort connectPort, string protocol = "tcp")
{
var output =
ExecuteCommand(
$"set {type.ToString().ToLower()} listenaddress=\"{listenAddress}\" listenport=\"{listenPort}\" connectAddress=\"{connectAddress}\" connectPort=\"{connectPort}\" protocol=\"{protocol}\"");
return output.Length > 0 ? output[0] : string.Empty;
}
public static string Set(PortProxyItem item)
{
return Set(item.Type, item.ListenAddress, item.ListenPort, item.TargetAddress!, item.TargetPort ?? 0);
}
private static string[] ExecuteCommand(string command)
{
var startInfo = new ProcessStartInfo
{
FileName = "netsh",
Arguments = $"interface portproxy {command}",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.UTF8
};
using var process = new Process();
process.StartInfo = startInfo;
process.Start();
var output = process.StandardOutput.ReadToEnd();
var error = process.StandardError.ReadToEnd();
process.WaitForExit();
var lines = new List<string>();
if (!string.IsNullOrEmpty(error))
lines.AddRange(error.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries));
lines.AddRange(output.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries));
return lines.ToArray();
}
private static PortProxyType? CheckPosition(string input)
{
var ipv4Index = input.IndexOf("ipv4", StringComparison.Ordinal);
var ipv6Index = input.IndexOf("ipv6", StringComparison.Ordinal);
if (ipv4Index != -1 && ipv6Index != -1)
{
if (ipv4Index < ipv6Index) return PortProxyType.V4ToV6;
if (ipv4Index > ipv6Index) return PortProxyType.V6ToV4;
return null;
}
if (ipv4Index != -1) return PortProxyType.V4ToV4;
if (ipv6Index != -1) return PortProxyType.V6ToV6;
return null;
}
}

View File

@@ -0,0 +1,10 @@
namespace PortProxyTool;
public class PortProxyItem
{
public required PortProxyType Type { get; set; }
public required string ListenAddress { get; set; }
public required ushort ListenPort { get; set; }
public required string? TargetAddress { get; set; }
public required ushort? TargetPort { get; set; }
}

View File

@@ -0,0 +1,9 @@
namespace PortProxyTool;
public enum PortProxyType
{
V4ToV4,
V4ToV6,
V6ToV6,
V6ToV4
}