Python - 简单实现SOCKS5-dailifuwuqi

该代码段展示了用Python和C#编写的简单代理服务器程序,用于获取本地网络信息,如端口和网络卡信息,并处理客户端连接。程序实现了数据转发功能,支持连接到指定地址并进行数据通信。同时,Python版本的代码包含了一个认证机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python版:

# -*- coding:utf-8 -*-
import os
import random
import socket
import threading
import select
import time

import psutil


class NetInfo(object):

    @staticmethod
    def get_port():
        """
        Gets the free port in the specified range
        :return: Available ports
        """
        net_cmd = "netstat -ntl |grep -v Active| grep -v Proto|awk '{print $4}'|awk -F: '{print $NF}'"
        port_list = os.popen(net_cmd).read().split("\n")
        port = random.randint(1024, 65535)
        if port not in port_list:
            return port
        else:
            NetInfo.get_port()

    @staticmethod
    def get_net_card():
        """Get the network card Ming and IP
        """
        card_list = []
        for card, values in psutil.net_if_addrs().items():
            if card == "lo":
                continue
            address = ""
            for key in values:
                if key.family == 2:
                    address = key.address
            if address == "":
                continue
            card_list.append(card + "-" + address)
        return card_list

    @staticmethod
    def get_local_ips():
        """Get all IP of the machine, not including 127.0.0.1"""
        res = [
            item[1]
            for k, v in psutil.net_if_addrs().items()
            for item in v
            if item[0] == 2
        ]
        if "127.0.0.1" in res:
            res.remove("127.0.0.1")
        return res[0]


def prxoy(sock, address):
    cs = sock
    DspPort = 0
    DspAddr = ''
    try:
        recv = cs.recv(512)
        VER = recv[0:1]
        # MethodNum=ord(recv[1:2])
        # Methods=[]
        # for i in range(0,MethodNum):
        # Methods.append(ord(recv[2+i:3+i]))
        if (IsNeedAuth):  # Need AUTHENICATION
            cs.send(b'\x05\x02')  # Reply
            recv = cs.recv(1024)
            Ver = recv[0:1]
            UserLen = ord(recv[1:2])
            User = recv[2:2 + UserLen]
            PassLen = ord(recv[2 + UserLen:3 + UserLen])
            Pass = recv[3 + UserLen:3 + UserLen + PassLen]
            if (User == Username and Pass == Password):
                cs.send(Ver + '\x00')
            else:
                cs.send(Ver + '\xff')
                cs.close()
                return
        else:
            cs.send(VER + '\x00')  # NO AUTHENICATION REQUEST
        try:
            recv = cs.recv(1024)
        except Exception, ex:
            print 'Client is Closed'
            return
        print("recv = {}".format(recv))
        CMD = ord(recv[1:2])
        ATYP = ord(recv[3:4])
        print("CMD = {}, ATYP = {}".format(CMD, ATYP))
        if (CMD == 0x01):  # CONNECT CMD
            if (ATYP == 03):  # DOMAINNAME
                AddrLen = ord(recv[4:5])
                DspPort = 256 * ord(recv[5 + AddrLen:5 + AddrLen + 1]) + ord(recv[1 + 5 + AddrLen:5 + AddrLen + 2])
                DspAddr = socket.gethostbyname(recv[5:5 + AddrLen])
            elif (ATYP == 01):  # IPV4
                if (recv.count('.') == 4):  # Asiic  format  split by  '.'
                    AddrLen = ord(recv[4:5])
                    DspAddr = recv[5:5 + AddrLen]
                    DspPort = 256 * ord(recv[5 + AddrLen:5 + AddrLen + 1]) + ord(recv[5 + AddrLen + 1:5 + AddrLen + 2])
                else:  # four hex number format
                    DspAddr = recv[4:8]
                    DspAddrr = ''
                    for i in DspAddr:
                        DspAddrr += str(ord(i)) + '.'
                    DspAddr = DspAddrr[:-1]
                    DspPort = 256 * ord(recv[4 + 4:4 + 4 + 1]) + ord(recv[4 + 4 + 1:4 + 4 + 2])
            else:
                print "IPV6 is not support"
                return
            cs.send(VER + '\x00\x00\x01\x00\x00\x00\x00\x00\x00')  # REPLY
            forward(cs, DspAddr, DspPort)
        else:
            print "Don't suport  this Cmd", CMD
    except Exception, e:
        print e


def forward(cs, DspAddr, DspPort):
    try:
        # print DspAddr +'\n'
        ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        ss.connect((DspAddr, DspPort))
    except Exception, e:
        print "Connect to ", DspAddr, "Fail"
        return
    socks = []
    socks.append(cs)
    socks.append(ss)
    while (True):
        try:
            r, w, e = select.select(socks, [], [])
            for s in r:
                if s is cs:
                    recv = cs.recv(2048)
                    caddr, cport = cs.getpeername()
                    if (len(recv) > 0):
                        saddr, sport = ss.getpeername()
                        print caddr, ':', cport, '<', len(recv), '>', saddr, ':', sport
                        ss.send(recv)

                    else:
                        for sock in socks:
                            sock.close()
                        return
                elif s is ss:
                    recv = ss.recv(2048)
                    saddr, sport = ss.getpeername()
                    if (len(recv) > 0):
                        caddr, cport = cs.getpeername()
                        print saddr, ':', sport, '<', len(recv), '>', caddr, ':', cport
                        cs.send(recv)
                    else:
                        for sock in socks:
                            sock.close()
                        return
        except Exception, e:
            print "Translate data error"
            break


if __name__ == "__main__":
    IsNeedAuth = True
    Username = 'admin'
    Password = '123456'
    host, port = NetInfo.get_local_ips(), NetInfo.get_port()
    print("host = {}, port = {}, username = {}, password = {}".format(host, port, Username, Password))
    ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ls.bind((host, port))
    ls.listen(500)
    while (True):
        clientSock, address = ls.accept()
        thread = threading.Thread(target=prxoy, args=(clientSock, address))
        thread.start()

C#版:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Collections;

namespace ProxyTest
{
    class Program
    {
        static string Username = "test";

        static string Password = "test";

        static public bool IsRun = false;
        static bool IsNeedAuth = false;
        static Socket ProxySocket;
        static int ListenPort = 1080;
        static ArrayList ClientSocks = new ArrayList();
        static int SockNum = 0;
        static object obj = new object();
        static void BeginProxy()
        {
            IsRun = true;
            IPAddress ip = IPAddress.Parse("0.0.0.0");
            ProxySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            ProxySocket.Bind(new IPEndPoint(ip, ListenPort));
            ProxySocket.Listen(100);
            Console.WriteLine("Bind On 0.0.0.0:" + ListenPort.ToString());
            while (IsRun)
            {
                try
                {
                    Socket clientSocket = ProxySocket.Accept();
                    Console.WriteLine(" 接受了来自 " + ((IPEndPoint)clientSocket.RemoteEndPoint).Address.ToString() +":" +((IPEndPoint)clientSocket.RemoteEndPoint).Port.ToString() + "的连接");
                    ClientSocks.Add(clientSocket);
                    Thread T = new Thread(ProcessClient);
                    T.Start(clientSocket);
                }
                catch
                {
                    break;
                }
            }

        }



        static void StartTransData(Socket clisock, Socket sersock)
        {
            int SocketNum;
            byte[] RecvBuf = new byte[1024*4];
            lock (obj)
            {
                SocketNum = ++SockNum;
            }
            int Len;


            String DstHost = ((IPEndPoint)sersock.RemoteEndPoint).Address.ToString() + ":";
            DstHost += ((IPEndPoint)sersock.RemoteEndPoint).Port.ToString();
            String SrcHost = ((IPEndPoint)sersock.LocalEndPoint).Address.ToString() + ":";
            SrcHost += ((IPEndPoint)sersock.LocalEndPoint).Port.ToString();
            while (IsRun)
            {

                try
                {
                    if (clisock.Poll(1000, SelectMode.SelectRead))
                    {

                        Len = clisock.Receive(RecvBuf);



                        if (Len == 0)
                        {
                            clisock.Shutdown(SocketShutdown.Both);
                            clisock.Close();
                            sersock.Shutdown(SocketShutdown.Both);
                            sersock.Close();
                            break;
                        }
                        else
                        {
                            Len = sersock.Send(RecvBuf, 0, Len, 0);
                            Console.WriteLine("【" + SockNum.ToString() + "】" +  SrcHost + "==>" + DstHost + "[发送" + Len.ToString() + "字节]");


                        }

                    }
                    if (sersock.Poll(1000, SelectMode.SelectRead))
                    {

                        Len = sersock.Receive(RecvBuf);


                        if (Len == 0)
                        {
                            sersock.Shutdown(SocketShutdown.Both);
                            sersock.Close();
                            clisock.Shutdown(SocketShutdown.Both);
                            clisock.Close();
                            break;
                        }
                        else
                        {
                            Len = clisock.Send(RecvBuf, 0, Len, 0);
                            Console.WriteLine("【" + SockNum.ToString() + "】" + DstHost + " ==> " + SrcHost + " [接收" + Len.ToString() + "字节]");


                        }



                    }
                }
                catch
                {

                    break;


                }
            }


        }
        static void ProcessClient(object sock)
        {
            byte[] RecvBuf = new byte[1024];
            Socket CliSock = (Socket)sock;
            Socket ServerSock;
            IPAddress ip = null;
            int Port = 0;
            byte[] buf = new byte[1024];
            int Len = 0;
            try
            {
                Len = CliSock.Receive(buf);

                byte SockVer = buf[0];

                if (IsNeedAuth)
                {
                    CliSock.Send(new byte[] { 0x05, 0x02 });  //需要验证
                    Len = CliSock.Receive(buf);
                    byte UserLen = buf[1];
                    byte[] User = new byte[UserLen];
                    Buffer.BlockCopy(buf, 2, User, 0, UserLen);



                    byte PassLen = buf[2 + UserLen];
                    byte[] Pass = new byte[PassLen];

                    Buffer.BlockCopy(buf, 3 + PassLen, Pass, 0, PassLen);
                    if (Encoding.ASCII.GetString(User) == Username && Encoding.ASCII.GetString(Pass) == Password)
                    {
                        CliSock.Send(new byte[] { 0x05, 0x00 });
                    }
                    else
                    {
                        CliSock.Send(new byte[] { 0x05, 0xff });
                        CliSock.Close();
                    }
                }
                else
                {
                    CliSock.Send(new byte[] { 0x05, 0x00 });
                }
            }
            catch
            {

            }
            try
            {
                Len = CliSock.Receive(RecvBuf);
                byte CMD = RecvBuf[1];
                byte ATYP = RecvBuf[3];
                if (CMD == 0x01)
                {
                    if (ATYP == 0x01)
                    {
                        if (RecvBuf.ToString().Split('.').Length == 5)
                        {
                            byte AddrLen = RecvBuf[4];
                            byte[] Addr = new byte[AddrLen];
                            Buffer.BlockCopy(RecvBuf, 5, Addr, 0, AddrLen);
                            IPAddress[] ips = Dns.GetHostAddresses(Addr.ToString());
                            ip = ips[0];
                            Port = 256 * RecvBuf[AddrLen + 5] + RecvBuf[AddrLen + 6];
                        }
                        else
                        {
                            byte[] Addr = new byte[4];
                            Buffer.BlockCopy(RecvBuf, 4, Addr, 0, 4);
                            String sip = "";
                            foreach (byte b in Addr)
                            {
                                sip += b.ToString() + ".";
                            }
                            IPAddress[] ips = Dns.GetHostAddresses(sip.Remove(sip.Length - 1));
                            ip = ips[0];
                            Port = 256 * RecvBuf[9] + RecvBuf[10];
                        }
                    }
                    else if (ATYP == 0x03)
                    {
                        byte AddrLen = RecvBuf[4];
                        byte[] Addr = new byte[AddrLen];
                        Buffer.BlockCopy(RecvBuf, 5, Addr, 0, AddrLen);

                        String HostName = System.Text.Encoding.Default.GetString(Addr);
                        IPAddress[] ips = Dns.GetHostAddresses(HostName);
                        ip = ips[0];
                        Port = 256 * RecvBuf[AddrLen + 5] + RecvBuf[AddrLen + 6];
                    }

                    else
                    {

                        return;
                    }

                    CliSock.Send(new byte[] { 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
                }
            }
            catch
            {
                return;
            }

            try
            {
                ServerSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                ServerSock.Connect(ip, Port);

                StartTransData(CliSock, ServerSock);
            }
            catch
            {
                CliSock.Shutdown(SocketShutdown.Both);
                CliSock.Close();
                return;
            }


        }

        static void Main(string[] args)
        {
            BeginProxy();
        }
    }
}


 

Python-socks是一个用于处理SOCKS代理Python库。如果在使用Python时出现了"Python Socks is needed for SOCKS proxying but is not available"的错误提示,可以通过执行命令"pip3 install python-socks"来安装python-socks库。接下来,可以使用以下代码示例来设置和使用SOCKS代理: ```python import socks # 创建socket s = socks.socksocket() # 设置代理相关信息 (username, password, ip, port) = ('', '', '', 0) s.set_proxy(socks.SOCKS5, addr=ip, port=port, username=username, password=password) # 连接目标网站 s.connect(("www.baidu.com", 80)) # 发送GET请求 s.sendall(b'GET / HTTP/1.1\n\r' b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8\n\r' b'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) Gecko/20100101 Firefox/99.0\n\r' b'\n\r') # 读取GET响应结果 print(s.recv(4096).decode(encoding='UTF-8')) ``` 上述代码中,首先导入了socks库,然后创建了一个socksocket对象s。通过调用s.set_proxy()方法设置了SOCKS5代理的相关信息,包括代理类型、地址、端口,以及可选的用户名和密码。接下来,调用s.connect()方法连接到目标网站。最后,使用s.sendall()发送GET请求,并使用s.recv()方法读取响应结果。 请注意,代码中的用户名、密码、代理地址、代理端口以及请求头部信息需要根据实际情况进行修改。并且需要确保已经安装了python-socks库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Python | 使用Socks5](https://blog.csdn.net/yimtcode/article/details/124541695)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [python中socks包(SocksiPy)的安装、使用方法简介](https://blog.csdn.net/qq_27378621/article/details/81012561)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值