使用linux的NAT功能可以把网络流量转发到特定端口上,然后我们可以写一个程序来处理这个端口上的数据,通过一些操作转发到对应服务器上来实现透明代理功能。
前段时间闲来无事研究了一下在.net core下如何做这些事情。下面是获取通过NAT转发过的数据包的源IP,端口信息的部分逻辑。
主要使用了libc下的getsockopt来获取源信息,对应的c语言代码网上可以找到很多,下面是用.net core的实现。
[DllImport("libc" ,CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static unsafe extern int getsockopt(IntPtr socket, SocketLevel level, SocketOptionName option_name,void* option_value, ref int option_len);
public unsafe static IPEndPoint GetTCPOriginAddr(IntPtr handle)
{
var size = 128;
var buff = stackalloc byte[size];
int r = getsockopt(handle, SocketLevel.SOL_IP, SocketOptionName.SO_ORIGINAL_DST, buff, ref size);
if (r != 0)
{
r = getsockopt(handle, SocketLevel.SOL_IPV6, SocketOptionName.SO_ORIGINAL_DST, buff, ref size);
if (r != 0)
throw new Exception("can not get dst addr");
}
return new IPEndPoint(GetNetIP(buff), GetNetPort(buff));
}
public static unsafe IPAddress GetIPV4(byte* buff, ref int pos)
{
//大端法机器
uint result = GetNetIP(buff);
return IPAddress.Parse(result.ToString());
}
public static unsafe uint GetNetIP(byte* buff, int offset = 0)
{
//大端法机器
uint result = 0;
result |= (uint)buff[offset + 4 + 0];
result |= (uint)buff[offset + 4 + 1] << 8;
result |= (uint)buff[offset + 4 + 2] << 16;
result |= (uint)buff[offset + 4 + 3] << 24;
return result;
}
public static unsafe ushort GetNetPort(byte* buff, int offset = 0)
{
//大端法机器
ushort result = 0;
result |= (ushort)buff[offset + 2 + 1];
result |= (ushort)(buff[offset + 2 + 0] << 8);
return result;
}