DEV Community

Cover image for Setting up a SOCKS Proxy Server with Dante on AWS
Idris Akintobi
Idris Akintobi

Posted on

Setting up a SOCKS Proxy Server with Dante on AWS

A SOCKS proxy server serves various purposes. In this guide, we'll explore how to set up one using Dante on Amazon Web Services (AWS), particularly useful in scenarios such as running applications on a serverless solution where external services request your service's static public IP for whitelisting. As serverless solutions limit direct IP provision, employing a SOCKS proxy offers a versatile solution by routing all requests to the external service through the SOCKS server. It's advisable to assign a public static IP for the SOCKS server in this context. Additionally, we'll address another common use case: enhancing privacy and security by configuring our SOCKS server to route all requests through the dynamic public IP address assigned to the server instance during creation. For a guide on how to host this on Google Cloud, you can click here.

Requirements

To set up a SOCKS proxy server on AWS, you'll need:

  • An AWS account
  • A security group rule
  • An EC2 instance (virtual machine)

Security Group Rule Setup

  • Go to the AWS Management Console and navigate to the EC2 Dashboard > Security Groups.
    Create Security Group

  • Click on "Create Security Group." Name the security group (e.g., 'allow-sock-1047') and create a security group description.

  • Create security group Inbound Rules: Add a rule to allow incoming traffic on port 22 for ssh and your desired SOCKS port (e.g., port 1047). Apply additional security rules, such as IP restrictions, as needed.
    Create security group Inbound Rules

EC2 Instance Setup

  • Navigate to the EC2 Dashboard > Instances.

  • Click on "Launch Instance."

  • Name your instance (e.g., 'sock-server') and choose an Amazon Linux 2023 (AMI). If you opt for a different image, make sure to update the commands in the script to be compatible with the selected machine image.
    Launch instance

  • Choose an appropriate instance type (e.g., t2.micro, which is free-tier eligible).

  • Select an existing key pair or create a new one to access your instance securely.

  • Click 'Edit' in network settings and enable 'Auto-assign public IP.'

  • Click on 'Select existing security group' and choose the 'allow-sock-1047' rule.
    Network setting

  • Click 'Advanced options' and paste the script into the 'User Data' text area field.
    Paste user data script

  • Review your configurations and click on "Launch."

script

#!/bin/bash

# Set terminal type
export TERM=xterm-256color

# Variables
SOCK_USERNAME="socksproxy"
SOKSPROXY_PASS="socksproxy"
SOCK_PORT=1047

# Function to print stage
print_stage() {
    local TEXT="$1"
    echo -e "\n\e[32m\e[1m $TEXT \e[0m\e[32m"
}

# Update system and install dante-server dependencies
print_stage "Updating System and install development tools"
# use yum to install if you've selected machine image earlier than 2023
sudo dnf update -y
sudo dnf groupinstall "Development Tools" -y
sudo dnf install libevent-devel -y

# Download and install dante-server
print_stage "Downloading and installing dante-server"
curl -O https://www.inet.no/dante/files/dante-1.4.3.tar.gz
tar xvzf dante-1.4.3.tar.gz
cd dante-1.4.3
./configure
make && make install

# Create dante configuration file
print_stage "Setting up dante-server"
cat <<EOF | tee /etc/sockd.conf
logoutput: /var/log/sockd.log
internal: 0.0.0.0 port = ${SOCK_PORT}
external: enX0
clientmethod: none
socksmethod: username
user.privileged: root
user.notprivileged: nobody
client pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
    log: error connect disconnect
}
socks pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
    log: error connect disconnect
}
EOF

# Add socksproxy user
print_stage "Adding ${SOCK_USERNAME} user"
sudo useradd -r -s /bin/false ${SOCK_USERNAME}
echo "${SOCK_USERNAME}:${SOKSPROXY_PASS}" | sudo chpasswd

# Start sockd
sudo /usr/local/sbin/sockd -D

print_stage "Installation Completed"

# Get public IP address (metadata version 1)
# PUBLIC_IPV4=$(curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address 2>/dev/null || echo "N/A")

# Get public IP address (metadata version 2 - token required)
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null)
PUBLIC_IPV4=$(curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null || echo "N/A")

# Display configuration details and IP addresses
print_stage "Configuration Details:"
echo -e "\033[1mIP:\033[0m ${PUBLIC_IPV4}"
echo -e "\033[1mUsername:\033[0m ${SOCK_USERNAME}"
echo -e "\033[1mPassword:\033[0m ${SOKSPROXY_PASS}"
echo -e "\033[1mPort:\033[0m ${SOCK_PORT}"
Enter fullscreen mode Exit fullscreen mode

Script Explanation

For brevity, we'll focus on the Dante configuration in the script. For more configuration options you can visit here. The script uses Dante version 1.4.3 which is the latest at the time of writing this article. Version 1.5 is currently in testing phase and it is set to roll out first quarter of this year.

logoutput: /var/log/sockd.log: Specifies the path for the log file. In this case, it will be stored at /var/log/sockd.log.
internal: 0.0.0.0 port = ${SOCK_PORT}: Configures the internal IP address and port on which the SOCKS server will listen for incoming connections. The variable ${SOCK_PORT} is used to set the specified port (in this case, 1047).
external: ens4: Defines the external network interface to bind to. In this script, it uses the interface ens4.
clientmethod: none: Specifies that clients connecting to the SOCKS server do not need to authenticate.
socksmethod: username: Specifies that the SOCKS server will use username/password authentication for connections.
user.privileged: root: Sets the privileged user for the SOCKS server to root.
user.notprivileged: nobody: Sets the non-privileged user for the SOCKS server to nobody.
client pass { … }: Defines a rule allowing connections from any IP (0.0.0.0/0) to any destination. It logs errors related to connection and disconnection.
socks pass { … }: Similar to the client pass rule, this allows SOCKS connections from any IP to any destination and logs related errors.

Once the instance is running, SSH into it to view the script log using cat /var/log/cloud-init-output.log. Please note that the script might take a while to complete due to the compilation of Dante and the use of a small machine type.
You can also rerun the startup script from the SSH terminal by using sudo bash /var/lib/cloud/instance/user-data.txt. This could be useful when you edit the instance startup script and need to rerun it manually.

Testing the SOCKS Proxy

  • Check if the configured port is open using:
nc -zv ${IP} ${PORT}
Enter fullscreen mode Exit fullscreen mode
  • Verify the SOCKS server functionality by curling Google's home page with the command:
socks5://${USERNAME}:${PASS}@${IP}:${PORT} https://www.google.com
Enter fullscreen mode Exit fullscreen mode

SOCKS Usage

  • In browser
    Install the Proxy Toggle Firefox extension and configure it with the SOCKS settings to route browser traffic through the SOCKS server.
    Proxy Toggle Firefox extension configuration

  • In code
    Use Axios in JavaScript with the socks-proxy-agent module for making requests through the SOCKS server.

import axios from 'axios';
import { SocksProxyAgent } from 'socks-proxy-agent';

// Get socks config from the environment. - Assuming the variables are available
const { SOCKS_HOST, SOCKS_PORT, SOCKS_USERNAME, SOCKS_PASSWORD } = process.env;

// Setup proxy agent
const socksV5Agent = new SocksProxyAgent(`socks5://${SOCKS_USERNAME}:${SOCKS_PASSWORD}@${SOCKS_HOST}:${SOCKS_PORT}`);

// Create socks axios instance
const socksClient = axios.create({
    httpsAgent: socksV5Agent,
    httpAgent: socksV5Agent,
});

// Use the instance 
(async () => {
    try {
        const { data } = await socksClient.get('https://api.ipify.org');
        console.log(`Our socks IP is ${data}`);
    } catch (error) {
        console.error('Error fetching IP:', error.message);
        // Handle the error as needed
    }
})();
Enter fullscreen mode Exit fullscreen mode

Conclusion

In conclusion, this guide has equipped you with the knowledge and step-by-step instructions to seamlessly set up a SOCKS proxy server on AWS using Dante. By following the outlined procedures, you can establish a robust SOCKS proxy server ready to meet your specific needs.

Top comments (0)