Email
Enterprise Service
menu
Email
Enterprise Service
Submit
Basic information
Waiting for a reply
Your form has been submitted. We'll contact you in 24 hours.
Close
Home/ Blog/ How to write a simple Socks5 proxy server in Golang?

How to write a simple Socks5 proxy server in Golang?

Author:PYPROXY
2025-01-13

Building a socks5 proxy server in Golang provides an excellent opportunity to explore network programming and the inner workings of proxy protocols. SOCKS5 is a protocol that facilitates client-server communication, often used for secure browsing or anonymized connections. The advantage of implementing a proxy server in Golang lies in its efficiency, ease of concurrent handling, and robust standard library for networking tasks. This article will guide you through the steps of creating a basic socks5 proxy server in Go, explaining key components such as connection handling, authentication (if needed), and data forwarding. By the end, you will understand the core principles of proxy servers and how to leverage Golang's concurrency features to build a functional and scalable SOCKS5 server.

Understanding the Basics of SOCKS5 Protocol

Before diving into the implementation, it's essential to understand the SOCKS5 protocol's core functionality. SOCKS5 (Socket Secure version 5) is a flexible and powerful protocol that allows clients to connect to servers through a proxy. It supports both UDP and TCP connections and provides an additional layer of anonymity by masking the client's IP address.

The SOCKS5 protocol consists of three major components:

1. Handshake: This is the initial connection setup between the client and server.

2. Authentication: SOCKS5 supports various authentication methods, though many implementations do not require any authentication (simple authentication).

3. Request Handling: The server forwards requests from the client to the target server based on the request type (TCP or UDP).

For the sake of simplicity, this article will focus on building a basic version of a SOCKS5 proxy server with minimal authentication and no UDP support.

Setting Up Golang Development Environment

To start building your SOCKS5 proxy server in Golang, ensure that you have a Go development environment set up on your system. If you haven’t installed Go yet, download and install the latest version from the official Go website.

Once installed, you can verify your installation by typing the following command in your terminal:

```

go version

```

You should see the Go version displayed, confirming that Go is successfully installed.

Step-by-Step Guide to Building a SOCKS5 Proxy Server in Golang

Now that you have a basic understanding of the SOCKS5 protocol and Go environment, let’s walk through the steps to implement the proxy server.

Step 1: Creating the Server and Listening for Connections

The first step is to create a TCP listener that will handle incoming client connections. In Go, this is done using the `net` package, which provides an easy way to listen on a specific port.

```go

package main

import (

"fmt"

"net"

"os"

)

func main() {

// Create a TCP listener on port 1080

listener, err := net.Listen("tcp", ":1080")

if err != nil {

fmt.Println("Error creating listener:", err)

os.Exit(1)

}

defer listener.Close()

fmt.Println("SOCKS5 proxy server listening on port 1080...")

// Accept incoming client connections

for {

conn, err := listener.Accept()

if err != nil {

fmt.Println("Error accepting connection:", err)

continue

}

go handleClient(conn) // Handle each client connection concurrently

}

}

```

In this code, we are listening on port `1080` for incoming client connections. When a connection is accepted, we spawn a new goroutine to handle the client asynchronously.

Step 2: Handling the SOCKS5 Handshake

Once the server accepts a connection from a client, the first task is to perform the SOCKS5 handshake. The client sends a version identifier and a list of supported authentication methods, and the server responds accordingly. For simplicity, we will implement a basic handshake without authentication.

```go

func handleClient(conn net.Conn) {

defer conn.Close()

// Step 1: Read the SOCKS5 version and authentication methods

buf := make([]byte, 2)

_, err := conn.Read(buf)

if err != nil {

fmt.Println("Error reading handshake:", err)

return

}

// Ensure the protocol version is SOCKS5

if buf[0] != 0x05 {

fmt.Println("Unsupported SOCKS version")

return

}

// Respond with the no authentication method selected

conn.Write([]byte{0x05, 0x00})

}

```

In this example, the client sends a two-byte message where the first byte is the version (0x05 for SOCKS5), and the second byte represents the number of supported authentication methods. The server responds by selecting `0x00`, indicating that no authentication is required.

Step 3: Handling the SOCKS5 Request

After the handshake, the client sends a request to the proxy server, indicating the desired action (e.g., TCP connect to a target server). The server must parse this request and handle the connection accordingly. Below is an example of how to handle a TCP connection request.

```go

func handleClient(conn net.Conn) {

defer conn.Close()

// Step 1: Perform handshake (as shown earlier)

// Step 2: Read the client request

buf := make([]byte, 4)

_, err := conn.Read(buf)

if err != nil {

fmt.Println("Error reading request:", err)

return

}

// The first byte indicates the command (0x01 for TCP connect)

if buf[0] != 0x01 {

fmt.Println("Unsupported command")

return

}

// Extract the target address and port

address := fmt.Sprintf("%d.%d.%d.%d", buf[1], buf[2], buf[3], buf[4])

port := int(buf[5])<<8 + int(buf[6])

// Step 3: Connect to the target server

targetConn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", address, port))

if err != nil {

fmt.Println("Error connecting to target:", err)

return

}

// Step 4: Respond to the client with success

conn.Write([]byte{0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})

// Step 5: Forward data between client and target

go forwardData(conn, targetConn)

go forwardData(targetConn, conn)

}

// Forward data between two connections

func forwardData(src, dst net.Conn) {

_, err := io.Copy(dst, src)

if err != nil {

fmt.Println("Error forwarding data:", err)

}

}

```

In this section, the server reads the client’s request, which includes the destination IP address and port. The server then attempts to connect to the requested target server. If successful, the server sends a success message back to the client and begins forwarding data between the client and the target server.

Step 4: Testing and Debugging

Once you’ve implemented the basic SOCKS5 proxy server, it’s essential to test it thoroughly. Use a SOCKS5-compatible client to connect to your server and verify that the proxy forwards requests correctly. You can also debug the server by printing log messages or using a tool like Wireshark to analyze network traffic.

Conclusion

Building a simple SOCKS5 proxy server in Golang is a great exercise in networking and concurrent programming. By understanding the SOCKS5 protocol, setting up a listener, handling client connections, and forwarding data, you can create a functional proxy server that supports basic TCP requests. Although this example is minimalistic, you can extend it by adding features like authentication, support for UDP, logging, and encryption for enhanced security.

This project not only enhances your skills in Go but also deepens your understanding of networking concepts that are widely used in real-world applications such as secure browsing, firewalls, and network tunneling.