mirror of
https://github.com/snltty/linker.git
synced 2025-10-28 19:31:50 +08:00
184 lines
5.7 KiB
C#
184 lines
5.7 KiB
C#
using linker.libs;
|
||
using linker.libs.extends;
|
||
using Microsoft.Win32.SafeHandles;
|
||
using System.Net;
|
||
|
||
namespace linker.tun
|
||
{
|
||
internal sealed class LinkerOsxTunDevice : ILinkerTunDevice
|
||
{
|
||
|
||
private string name = string.Empty;
|
||
public string Name => name;
|
||
public bool Running => fs != null;
|
||
|
||
private FileStream fs = null;
|
||
private IPAddress address;
|
||
private byte prefixLength = 24;
|
||
private SafeFileHandle safeFileHandle;
|
||
|
||
private string interfaceOsx = string.Empty;
|
||
|
||
public LinkerOsxTunDevice(string name)
|
||
{
|
||
this.name = name;
|
||
}
|
||
|
||
public bool Setup(IPAddress address, IPAddress gateway, byte prefixLength, out string error)
|
||
{
|
||
error = string.Empty;
|
||
|
||
interfaceOsx = GetOsxInterfaceNum();
|
||
this.address = address;
|
||
this.prefixLength = prefixLength;
|
||
|
||
safeFileHandle = File.OpenHandle($"/dev/{Name}", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, FileOptions.Asynchronous);
|
||
fs = new FileStream(safeFileHandle, FileAccess.ReadWrite, 1500);
|
||
|
||
IPAddress network = NetworkHelper.NetworkIP2IP(address, NetworkHelper.PrefixLength2Value(prefixLength));
|
||
CommandHelper.Osx(string.Empty, new string[] {
|
||
$"route delete -net {network}/{prefixLength} {address}",
|
||
$"ifconfig {Name} {address} {address} up",
|
||
$"route add -net {network}/{prefixLength} {address}",
|
||
});
|
||
return true;
|
||
}
|
||
|
||
public void Shutdown()
|
||
{
|
||
if (fs != null)
|
||
{
|
||
safeFileHandle?.Dispose();
|
||
|
||
interfaceOsx = string.Empty;
|
||
fs.Close();
|
||
fs.Dispose();
|
||
fs = null;
|
||
}
|
||
IPAddress network = NetworkHelper.NetworkIP2IP(address, NetworkHelper.PrefixLength2Value(this.prefixLength));
|
||
CommandHelper.Osx(string.Empty, new string[] { $"route delete -net {network}/{prefixLength} {address}" });
|
||
}
|
||
|
||
public void AddRoute(LinkerTunDeviceRouteItem[] ips, IPAddress ip)
|
||
{
|
||
string[] commands = ips.Select(item =>
|
||
{
|
||
IPAddress _ip = NetworkHelper.NetworkIP2IP(item.Address, item.PrefixLength);
|
||
return $"route add -net {_ip}/{item.PrefixLength} {ip}";
|
||
}).ToArray();
|
||
if (commands.Length > 0)
|
||
{
|
||
CommandHelper.Osx(string.Empty, commands.ToArray());
|
||
}
|
||
}
|
||
public void DelRoute(LinkerTunDeviceRouteItem[] ip)
|
||
{
|
||
string[] commands = ip.Select(item =>
|
||
{
|
||
IPAddress _ip = NetworkHelper.NetworkIP2IP(item.Address, item.PrefixLength);
|
||
return $"route delete -net {_ip}/{item.PrefixLength}";
|
||
}).ToArray();
|
||
if (commands.Length > 0)
|
||
{
|
||
CommandHelper.Osx(string.Empty, commands.ToArray());
|
||
}
|
||
}
|
||
|
||
public void SetMtu(int value)
|
||
{
|
||
CommandHelper.Osx(string.Empty, new string[] { $"ifconfig {Name} mtu {value}" });
|
||
}
|
||
|
||
public void SetNat(out string error)
|
||
{
|
||
error = string.Empty;
|
||
/*
|
||
# 开启ip转发
|
||
sudo sysctl -w net.ipv4.ip_forward=1
|
||
# 配置NAT转发规则
|
||
# 在/etc/pf.conf文件中添加以下规则,en0是出口网卡,10.26.0.0/24是来源网段
|
||
nat on en0 from 10.26.0.0/24 to any -> (en0)
|
||
# 加载规则
|
||
sudo pfctl -f /etc/pf.conf -e
|
||
CommandHelper.Osx(string.Empty, new string[] {
|
||
"sysctl -w net.ipv4.ip_forward=1",
|
||
"nat on en0 from 10.26.0.0/24 to any -> (en0)",
|
||
"pfctl -f /etc/pf.conf -e",
|
||
});
|
||
*/
|
||
}
|
||
public void RemoveNat(out string error)
|
||
{
|
||
error = string.Empty;
|
||
}
|
||
|
||
public List<LinkerTunDeviceForwardItem> GetForward()
|
||
{
|
||
return new List<LinkerTunDeviceForwardItem>();
|
||
}
|
||
public void AddForward(List<LinkerTunDeviceForwardItem> forwards)
|
||
{
|
||
}
|
||
public void RemoveForward(List<LinkerTunDeviceForwardItem> forwards)
|
||
{
|
||
}
|
||
|
||
|
||
private byte[] buffer = new byte[2 * 1024];
|
||
public ReadOnlyMemory<byte> Read()
|
||
{
|
||
try
|
||
{
|
||
int length = fs.Read(buffer.AsSpan(4));
|
||
length.ToBytes(buffer);
|
||
return buffer.AsMemory(0, length + 4);
|
||
}
|
||
catch (Exception)
|
||
{
|
||
}
|
||
return Helper.EmptyArray;
|
||
}
|
||
|
||
public bool Write(ReadOnlyMemory<byte> buffer)
|
||
{
|
||
try
|
||
{
|
||
fs.Write(buffer.Span);
|
||
return true;
|
||
}
|
||
catch (Exception)
|
||
{
|
||
}
|
||
return false;
|
||
}
|
||
|
||
private string GetOsxInterfaceNum()
|
||
{
|
||
string output = CommandHelper.Osx(string.Empty, new string[] { "ifconfig" });
|
||
var arr = output.Split(Environment.NewLine);
|
||
for (int i = 0; i < arr.Length; i++)
|
||
{
|
||
var item = arr[i];
|
||
if (item.Contains("inet "))
|
||
{
|
||
for (int k = i; k >= 0; k--)
|
||
{
|
||
var itemk = arr[k];
|
||
if (itemk.Contains("flags=") && itemk.StartsWith("en"))
|
||
{
|
||
return itemk.Split(": ")[0];
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
return string.Empty;
|
||
}
|
||
|
||
public void Clear()
|
||
{
|
||
|
||
}
|
||
}
|
||
}
|