解决一下 WebView2 下 socket5代理不能启用账号密码的问题。

webview2现在好像还能在启用s5代理的情况下,可以输入账号密码。应该是还没开发这个API。所以曲线解决了一下,记录一下吧。

解决就是自己写代理转发认证一下。直接上代码 

    /// <summary>
    /// Socket代理5转发
    /// </summary>
    public class Socket5Forward
    {

        #region 类型 Type


        #region 私有类型 Private

        /// <summary>
        /// 进度命令
        /// </summary>
        private enum Command
        {
            /// <summary>
            /// 默认
            /// </summary>
            Default,

            /// <summary>
            /// 连接
            /// </summary>
            Connection,

            /// <summary>
            /// 验证
            /// </summary>
            Validate,

            /// <summary>
            /// 读写
            /// </summary>
            ReadWrite
        }


        /// <summary>
        /// 异步状态对象
        /// </summary>
        private class StateObject
        {
            /// <summary>
            /// 标识
            /// </summary>
            public long IntID { get; set; }

            /// <summary>
            /// 客户端-无认证
            /// </summary>
            public Socket ClientSocket { get; set; }

            /// <summary>
            /// 客户端-进度
            /// </summary>
            public Command ClientCommand { get; set; } = Command.Default;

            /// <summary>
            /// 客户端-数据包
            /// </summary>
            public List<ArraySegment<byte>> ClientRead { get; set; }




            /// <summary>
            /// 代理端-需认证
            /// </summary>

            public Socket ProxySocket { get; set; }

            /// <summary>
            /// 代理端-进度
            /// </summary>
            public Command ProxyCommand { get; set; } = Command.Default;

            /// <summary>
            /// 代理段-数据包
            /// </summary>
            public List<ArraySegment<byte>> ProxyRead { get; set; }


        }

        /// <summary>
        /// 代理数据
        /// </summary>
        public class Proxy
        {
            /// <summary>
            /// 代理IP
            /// </summary>
            public string IP { set; get; }

            /// <summary>
            /// 代理端口
            /// </summary>
            public int Port { set; get; }

            /// <summary>
            /// 代理用户
            /// </summary>
            public string User { set; get; }

            /// <summary>
            /// 代理密码
            /// </summary>
            public string Pass { set; get; }
        }




        #endregion 私有类型


        #region 公开类型 Public



        #endregion 公开类型


        #endregion 类型


        #region 属性 Propertie


        #region 私有属性 Private

        /// <summary>
        /// 代理信息
        /// </summary>
        private Proxy ObjProxy { get; set; }

        /// <summary>
        /// 自增标识
        /// </summary>
        private long IntID { get; set; } = 0;

        /// <summary>
        /// 服务对象
        /// </summary>
        private TcpListener ObjServer { get; set; }

        #endregion 私有属性



        #endregion 属性


        #region 构造 Constructor


        /// <summary>
        /// 构造对象
        /// </summary>
        /// <param name="sIp">代理IP</param>
        /// <param name="nPort">代理端口</param>
        /// <param name="sUser">代理用户</param>
        /// <param name="sPass">代理密码</param>
        public Socket5Forward(string sIp, int nPort, string sUser, string sPass)
        {
            ObjProxy = new Proxy
            {
                IP = sIp,
                Port = nPort,
                User = sUser,
                Pass = sPass
            };

            AddLog(System.Text.Json.JsonSerializer.Serialize(ObjProxy));
        }

        public Socket5Forward(Proxy oProxy)
        {
            ObjProxy = oProxy;
        }
        #endregion  构造


        #region 方法 Method


        #region 私有方法 Private

        /// <summary>
        /// 日志
        /// </summary>
        /// <param name="sMsg"></param>
        private static void AddLog(string sMsg)
        {
            System.Diagnostics.Trace.WriteLine(sMsg);
            //Console.WriteLine(sMsg);
        }

        #region 客户端

        /// <summary>
        /// 客户端-接受连接
        /// </summary>
        /// <param name="iAR"></param>
        private void ClientAccept(IAsyncResult iAR)
        {
            AddLog("客户端-连接");
            var listener = iAR.AsyncState as TcpListener;
            try
            {
                var oClientSocket = listener.EndAcceptSocket(iAR);
                var oProxyScoket = new TcpClient();
                var oState = new StateObject
                {
                    IntID = ++IntID,

                    ClientSocket = oClientSocket,
                    ClientCommand = Command.Connection,
                    ClientRead = new List<ArraySegment<byte>>() { new ArraySegment<byte>(new byte[oClientSocket.ReceiveBufferSize]) },

                    ProxySocket = oProxyScoket.Client,
                    ProxyRead = new List<ArraySegment<byte>>() { new ArraySegment<byte>(new byte[oClientSocket.ReceiveBufferSize]) }
                };
                _ = oProxyScoket.BeginConnect(ObjProxy.IP, ObjProxy.Port, ProxyConnect, oState);
                _ = listener.BeginAcceptSocket(ClientAccept, listener);
            }
            catch { }
        }

        /// <summary>
        /// 客户端-读取->转发
        /// </summary>
        /// <param name="iAR"></param>
        private void ClientRead(IAsyncResult iAR)
        {
            var oState = iAR.AsyncState as StateObject;
            try
            {
                var nRead = oState.ClientSocket.EndReceive(iAR);
                if (nRead > 0)
                {
                    if (oState.ClientCommand == Command.Connection)
                    {
                        AddLog($"[{oState.IntID}]客户端-请求命令");
                        var nFristMethod = oState.ClientRead[0].Array[2];
                        _ = oState.ClientSocket.Send(new byte[] { 0x05, nFristMethod });
                        oState.ClientCommand = Command.ReadWrite;

                    }
                    else if (oState.ClientCommand == Command.ReadWrite)
                    {
                        //var sText = Encoding.UTF8.GetString(oState.ClientRead[0].Array, 0, nRead);
                        //AddLog(sText);
                        var nSend = oState.ProxySocket.Send(oState.ClientRead[0].Array, nRead, SocketFlags.None);
                        AddLog($"[{oState.IntID}]客户端-转发数据包长度:R[{nRead}],S[{nSend}]");
                    }
                    _ = oState.ClientSocket.BeginReceive(oState.ClientRead, SocketFlags.None, ClientRead, oState);
                }
                else
                {
                    AddLog($"[{oState.IntID}]客户端-关闭:长度不足");
                    oState.ClientSocket.Close();
                    oState.ProxySocket.Close();
                }
            }
            catch (Exception)
            {
                AddLog($"[{oState.IntID}]客户端-关闭:异常关闭");
                oState.ClientSocket.Close();
                oState.ProxySocket.Close();
            }
        }

        #endregion

        #region 代理端

        /// <summary>
        /// 代理端-连接完成
        /// </summary>
        /// <param name="iAR"></param>
        private void ProxyConnect(IAsyncResult iAR)
        {
            try
            {
                AddLog("代理端已连接");
                var oState = iAR.AsyncState as StateObject;
                oState.ProxySocket.EndConnect(iAR);
                oState.ProxyCommand = string.IsNullOrEmpty(ObjProxy.User) || string.IsNullOrEmpty(ObjProxy.Pass) ? Command.Validate : Command.Connection;

                _ = oState.ProxySocket.Send(new byte[] { 0x05, 0x02, 0x00, 0x02 });
                _ = oState.ProxySocket.BeginReceive(oState.ProxyRead, SocketFlags.None, ProxyRead, oState);


            }
            catch { }

        }

        /// <summary>
        /// 代理端-读取->转发
        /// </summary>
        /// <param name="iAR"></param>
        private void ProxyRead(IAsyncResult iAR)
        {
            var oState = iAR.AsyncState as StateObject;
            try
            {
                var nRead = oState.ProxySocket.EndReceive(iAR);
                if (nRead > 0)
                {
                    //AddLog($"[{oState.IntID}]ProxyRead====nRead > 0 nRead=" + nRead);
                    if (oState.ProxyCommand == Command.Connection)
                    {
                        var arrBuf = oState.ProxyRead[0].Array;
                        AddLog($"[{oState.IntID}]代理端-返回连接方法:{arrBuf[0]:x},{arrBuf[1]:x}");
                        var oStream = new MemoryStream();
                        oStream.WriteByte(0x1);
                        oStream.WriteByte((byte)ObjProxy.User.Length);
                        oStream.Write(Encoding.ASCII.GetBytes(ObjProxy.User));
                        oStream.WriteByte((byte)ObjProxy.Pass.Length);
                        oStream.Write(Encoding.ASCII.GetBytes(ObjProxy.Pass));
                        _ = oState.ProxySocket.Send(oStream.ToArray());
                        oStream.Close();

                        oState.ProxyCommand = Command.Validate;
                    }
                    else if (oState.ProxyCommand == Command.Validate)
                    {
                        var arrBuf = oState.ProxyRead[0].Array;
                        AddLog($"[{oState.IntID}]代理端-返回验证结果:{arrBuf[0]:x},{arrBuf[1]:x}");
                        if (arrBuf[1] == 0x0)
                        {
                            AddLog($"[{oState.IntID}]客户端-接受数据");
                            _ = oState.ClientSocket.BeginReceive(oState.ClientRead, SocketFlags.None, ClientRead, oState);
                            oState.ProxyCommand = Command.ReadWrite;
                        }
                        else
                        {
                            AddLog($"[{oState.IntID}]代理端-认证错误");
                            oState.ProxySocket.Close();
                            oState.ClientSocket.Close();
                        }
                    }
                    else if (oState.ProxyCommand == Command.ReadWrite)
                    {
                        //var sText = Encoding.UTF8.GetString(oState.ProxyRead[0].Array);
                        var nSend = _ = oState.ClientSocket.Send(oState.ProxyRead[0].Array, nRead, SocketFlags.None);
                        AddLog($"[{oState.IntID}]代理端-转发数据包长度:R[{nRead}],S[{nSend}]");
                    }
                    _ = oState.ProxySocket.BeginReceive(oState.ProxyRead, SocketFlags.None, ProxyRead, oState);
                }
                else
                {
                    AddLog($"[{oState.IntID}]代理端-关闭:长度不足");
                    oState.ProxySocket.Close();
                    oState.ClientSocket.Close();
                }
            }
            catch (Exception)
            {

                AddLog($"[{oState.IntID}]代理端-关闭:异常");
                oState.ProxySocket.Close();
                oState.ClientSocket.Close();
            }
        }

        #endregion

        #endregion 私有方法


        #region 公开方法 Public

        /// <summary>
        /// 开始服务
        /// </summary>
        /// <param name="nProt"></param>
        public void Start(int nProt)
        {
            AddLog("开始");
            try
            {
                ObjServer = new TcpListener(IPAddress.Any, nProt);
                ObjServer.Start();
                _ = ObjServer.BeginAcceptSocket(ClientAccept, ObjServer);
            }
            catch (Exception)
            {
                ObjServer = null;
            }
        }


        public void Stop()
        {
            ObjServer?.Stop();
        }

        #endregion 公开方法


        #endregion 方法


    }

 

posted @ 2022-04-06 11:14  HackDragon  阅读(417)  评论(0编辑  收藏  举报