ZBLOG

Code example for socks5 proxy server in c++

Here’s an example of a simple SOCKS5 proxy server in C++ using the Boost Asio library:

#include <iostream>
#include <boost/asio.hpp>

using boost::asio::ip::tcp;

class socks5_session : public std::enable_shared_from_this<socks5_session>
{
public:
    socks5_session(tcp::socket socket) : socket_(std::move(socket)), state_(0)
    {
    }

    void start()
    {
        do_read();
    }

private:
    void do_read()
    {
        auto self(shared_from_this());
        socket_.async_receive(boost::asio::buffer(buffer_),
            [this, self](boost::system::error_code ec, std::size_t bytes_transferred)
            {
                if (!ec)
                {
                    switch (state_)
                    {
                    case 0: // authentication methods
                        if (buffer_[0] == 0x05 && buffer_[1] >= 1 && buffer_[2] <= 3)
                        {
                            // send selection message
                            buffer_[0] = 0x05;
                            buffer_[1] = 0x00; // no authentication required
                            boost::asio::async_write(socket_, boost::asio::buffer(buffer_, 2),
                                [this, self](boost::system::error_code ec, std::size_t /* bytes_transferred */)
                                {
                                    if (!ec)
                                    {
                                        state_ = 1;
                                        do_read();
                                    }
                                });
                        }
                        else
                        {
                            std::cerr << "Invalid authentication methods message\n";
                        }
                        break;

                    case 1: // connection request
                        if (buffer_[0] == 0x05 && buffer_[1] == 0x01 && buffer_[2] == 0x00)
                        {
                            // parse destination address
                            int addr_type = buffer_[3];
                            std::size_t addr_len;
                            if (addr_type == 0x01) // IPv4 address
                                addr_len = 4;
                            else if (addr_type == 0x03) // domain name
                                addr_len = buffer_[4] + 1;
                            else if (addr_type == 0x04) // IPv6 address
                                addr_len = 16;
                            else // invalid address type
                            {
                                std::cerr << "Invalid address type\n";
                                return;
                            }
                            if (bytes_transferred < 4 + addr_len + 2)
                            {
                                std::cerr << "Incomplete connection request message\n";
                                return;
                            }
                            std::string dest_addr(buffer_.begin() + 4, buffer_.begin() + 4 + addr_len);
                            int dest_port = buffer_[4 + addr_len] << 8 | buffer_[4 + addr_len + 1];

                            // connect to destination server
                            tcp::resolver resolver(socket_.get_io_service());
                            resolver.async_resolve(dest_addr, std::to_string(dest_port),
                                [this, self](boost::system::error_code ec, tcp::resolver::iterator it)
                                {
                                    if (!ec)
                                    {
                                        do_connect(it);
                                    }
                                });
                        }
                        else
                        {
                            std::cerr << "Invalid connection request message\n";
                        }
                        break;

                    case 2: // forward data
                        boost::asio::async_write(destination_socket_, boost::asio::buffer(buffer_, bytes_transferred),
                            [this, self](boost::system::error_code ec, std::size_t /* bytes_transferred */)
                            {
                                if (ec)
                                {
                                    std::cerr << "Forward error: " << ec.message() << "\n";
                                    socket_.close();
                                }
                                else
                                {
                                    do_read();
                                }
                            });
                        break;
                    }
                }
                else
                {
                    std::cerr << "Read error: " << ec.message() << "\n";
                    socket_.close();
                }
            });
    }

    void do_connect(tcp::resolver::iterator it)
    {
        auto self(shared_from_this());
        destination_socket_.async_connect(*it,
            [this, self](boost::system::error_code ec)
            {
                if (!ec)
                {
                    // send success message
                    buffer_[0] = 0x05;
                    buffer_[1] = 0x00; // success
                    buffer_[2] = 0x00; // reserved
                    buffer_[3] = 0x01; // IPv4 address
                    boost::asio::ip::address_v4 address = destination_socket_.remote_endpoint().address().to_v4();
                    std::memcpy(buffer_.data() + 4, &address, 4);
                    int port = destination_socket_.remote_endpoint().port();
                    buffer_[8] = port >> 8;
                    buffer_[9] = port & 0xff;
                    boost::asio::async_write(socket_, boost::asio::buffer(buffer_, 10),
                        [this, self](boost::system::error_code ec, std::size_t /* bytes_transferred */)
                        {
                            if (!ec)
                            {
                                state_ = 2;
                                do_read();
                            }
                        });
                }
                else
                {
                    std::cerr << "Connect error: " << ec.message() << "\n";
                    buffer_[0] = 0x05;
                    buffer_[1] = 0x03; // destination unreachable
                    buffer_[2] = 0x00; // reserved
                    boost::asio::async_write(socket_, boost::asio::buffer(buffer_, 3),
                        [this, self](boost::system::error_code ec, std::size_t /* bytes_transferred */)
                        {
                            socket_.close();
                        });
                }
            });
    }

    tcp::socket socket_;
    tcp::socket destination_socket_;
    std::array<char, 1024> buffer_;
    int state_;
};

class socks5_server
{
public:
    socks5_server(boost::asio::io_service& io_service, short port)
        : acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
    {
        do_accept();
    }

private:
    void do_accept()
    {
        acceptor_.async_accept([this](boost::system::error_code ec, tcp::socket socket)
            {
                if (!ec)
                {
                    std::make_shared<socks5_session>(std::move(socket))->start();
                }
                do_accept();
            });
    }

    tcp::acceptor acceptor_;
};

int main(int argc, char* argv[])
{
    try
    {
        if (argc != 2)
        {
            std::cerr << "Usage: socks5_server <port>\n";
            return 1;
        }

        boost::asio::io_service io_service;
        socks5_server server(io_service, std::atoi(argv[1]));
        io_service.run();
    }
    catch (std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

This code listens on a specified port for incoming SOCKS5 connections, and proxies the TCP traffic to the destination server. It supports both IPv4 and domain name destinations. Note that this is just a basic example and doesn’t handle all possible error conditions or edge cases.

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=54

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?