# C# NetFilter2 SDK备忘

C# NetFilter2 SDK备忘,记录一些重要部分

  • NF_FILTERING_FLAG,NF_FILTER用于过滤,流量统计,流量限制什么的,NF_INDICATE_CONNECT_REQUESTS用于重定向连接,像TCP,可以修改目标ip端口,实现代理
  • remoteAddress,0,1,2,3,4,5,6,7,8,0 1 ip类型,2 3 端口,如果ipv4,紧跟着4字节,4-7,如果ipv6,跳过4字节,后面16字节,8-23

官方demo示例代理项目实现

设置规则定义

C#
public void SetRule()
{

List<NF_RULE> rules = new List<NF_RULE>();
//劫持53 DNS端口
rules.AddRange(new NF_RULE[] {
    //TCP 53
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_INDICATE_CONNECT_REQUESTS,
        protocol = (int)ProtocolType.Tcp,
        remotePort = BinaryPrimitives.ReverseEndianness((ushort)53),
        ip_family = (ushort)AddressFamily.InterNetwork
    },
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_INDICATE_CONNECT_REQUESTS,
        protocol = (int)ProtocolType.Tcp,
        remotePort = BinaryPrimitives.ReverseEndianness((ushort)53),
        ip_family = (ushort)AddressFamily.InterNetworkV6
    },
     //UDP 53
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_FILTER,
        protocol = (int)ProtocolType.Udp,
        remotePort = BinaryPrimitives.ReverseEndianness((ushort)53),
        ip_family = (ushort)AddressFamily.InterNetwork
    },
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_FILTER,
        protocol = (int)ProtocolType.Udp,
        remotePort = BinaryPrimitives.ReverseEndianness((ushort)53),
        ip_family = (ushort)AddressFamily.InterNetworkV6
    }
});

//放行IPV6局域网段
rules.AddRange(new NF_RULE[]
{
    //IPV6 环回 ::1/128
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_ALLOW,
        ip_family = (ushort)AddressFamily.InterNetworkV6,
        remoteIpAddress = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
        remoteIpAddressMask = new byte[] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
    },
    //IPV6 组播 FF00::/8
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_ALLOW,
        ip_family = (ushort)AddressFamily.InterNetworkV6,
        remoteIpAddress = new byte[] { 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        remoteIpAddressMask = new byte[] { 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    },
    //本地链路 FE80::/10
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_ALLOW,
        ip_family = (ushort)AddressFamily.InterNetworkV6,
        remoteIpAddress = new byte[] { 0xFE, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        remoteIpAddressMask = new byte[] { 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    },
    //本地站点 FEC0::/10
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_ALLOW,
        ip_family = (ushort)AddressFamily.InterNetworkV6,
        remoteIpAddress = new byte[] { 0xFE, 0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        remoteIpAddressMask = new byte[] { 255, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    }
});

//放行ipv4局域网段
List<string> intranetIpv4s = new List<string>() {
    "10.0.0.0/8", "100.64.0.0/10",
    "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12",
    "192.0.0.0/24", "192.0.2.0/24","192.88.99.0/24","192.168.0.0/16",
    "198.18.0.0/15","198.51.100.0/24",
    "203.0.113.0/24","224.0.0.0/4", "240.0.0.0/4","255.255.255.255/32"
};
foreach (string item in intranetIpv4s)
{
    string[] arr = item.Split('/');
    uint mask = BinaryPrimitives.ReverseEndianness(0xffffffff << (32 - byte.Parse(arr[1])));
    rules.Add(new NF_RULE
    {
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_ALLOW,
        ip_family = (ushort)AddressFamily.InterNetwork,
        remoteIpAddress = IPAddress.Parse(arr[0]).GetAddressBytes(),
        remoteIpAddressMask = BitConverter.GetBytes(mask),

    });
}

//劫持广域网段
rules.AddRange(new List<NF_RULE> { 
    //TCP
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_INDICATE_CONNECT_REQUESTS,
        protocol = (int)ProtocolType.Tcp,
        ip_family = (ushort)AddressFamily.InterNetwork
    },
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_INDICATE_CONNECT_REQUESTS,
        protocol = (int)ProtocolType.Tcp,
        ip_family = (ushort)AddressFamily.InterNetworkV6
    },
    //UDP
     new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_FILTER,
        protocol = (int)ProtocolType.Udp,
        ip_family = (ushort)AddressFamily.InterNetwork
    },
    new NF_RULE
    {
        direction = (byte)NF_DIRECTION.NF_D_OUT,
        filteringFlag = (uint)NF_FILTERING_FLAG.NF_FILTER,
        protocol = (int)ProtocolType.Udp,
        ip_family = (ushort)AddressFamily.InterNetworkV6
    },

});
NFAPI.nf_setRules(rules.ToArray());
}

数据事件处理定义

C#
//实现 NF_EventHandler 接口

//实现
public void udpCreated(ulong id, NF_UDP_CONN_INFO pConnInfo)
{
    //不是需要代理的进程
    if (xxx == false)
    {
        NFAPI.nf_udpDisableFiltering(pConnInfo.processId);
        return;
    }
    //创建连接
}
public void udpSend(ulong id, nint remoteAddress, nint buf, int len, nint options, int optionsLen)
{
    //是否有连接对象,没连接对象则直接发送数据,不代理
    if (xxx == false)
    {
        NFAPI.nf_udpPostSend(id, remoteAddress, buf, len, options);
        return;
    }

    //获取端口,方便判断是否是53 DNS协议
    byte* p = (byte*)remoteAddress;
    ushort port = (ushort)((*(p + 2) << 8 & 0xFF00) | *(p + 3));
    
    //构建代理连接
}
public unsafe void tcpConnectRequest(ulong id, ref NF_TCP_CONN_INFO pConnInfo)
{
    //不是需要代理的进程
    if (xxx == false)
    {
        NFAPI.nf_tcpDisableFiltering(pConnInfo.processId);
        return;
    }

    //更改目标地址到劫持服务器
}

安装驱动定义

C#
//一些定义
string SystemDriver = $"{Environment.SystemDirectory}\\drivers\\netfilter2.sys";
string NFDriver = "nfdriver.sys";
string Name = "netfilter2";

//检查文件版本
private string GetFileVersion(string file)
    {
        if (File.Exists(file))
            return FileVersionInfo.GetVersionInfo(file).FileVersion ?? "";

        return "";
    }
//检查驱动
private void CheckDriver()
{
    var binFileVersion = GetFileVersion(NFDriver);
    var systemFileVersion = GetFileVersion(SystemDriver);

    if (File.Exists(SystemDriver) == false)
    {
        InstallDriver();
        return;
    }

    var reinstall = false;
    if (Version.TryParse(binFileVersion, out var binResult) && Version.TryParse(systemFileVersion, out var systemResult))
    {
        if (binResult.CompareTo(systemResult) > 0)
            reinstall = true;
        else if (systemResult.Major != binResult.Major)
            reinstall = true;
    }
    else
    {
        if (!systemFileVersion.Equals(binFileVersion))
            reinstall = true;
    }

    if (!reinstall)
        return;

    UninstallDriver();
    InstallDriver();
}
//注册驱动
private void InstallDriver()
{
    if (!File.Exists(NFDriver))
        throw new Exception("builtin driver files missing, can't install NF driver");

    try
    {
        File.Copy(NFDriver, SystemDriver);
    }
    catch (Exception e)
    {
        throw new Exception($"Copy {Name}.sys failed\n{e.Message}");
    }

    // 注册驱动文件
    if (NFAPI.nf_registerDriver(Name) == NF_STATUS.NF_STATUS_SUCCESS)
    {
        Console.WriteLine($"Install {Name} driver finished");
    }
    else
    {
        Console.WriteLine($"Register {Name} failed");
    }
}
//删除驱动
private bool UninstallDriver()
{
    if (File.Exists(SystemDriver) == false)
        return true;

    NFAPI.nf_unRegisterDriver(Name);
    File.Delete(SystemDriver);

    return true;
}

安装驱动

C#
//检查安装驱动
CheckDriver();
//给驱动获取进程权限
NFAPI.nf_adjustProcessPriviledges();
//初始化驱动
NF_STATUS nF_STATUS = NFAPI.nf_init(Name, hijackEventHandler);
if (nF_STATUS != NF_STATUS.NF_STATUS_SUCCESS)
{
    throw new Exception($"{Name} start failed.{nF_STATUS}");
}
//设置规则
SetRule();

卸载驱动

C#
NFAPI.nf_deleteRules();
NFAPI.nf_free();