Setup a proxy forward with 3Proxy, Squid & Laravel
In this article we will explore how to build a proxy forwarder with 3Proxy, Squid and Laravel. We will cover how to setup the proxies, how to authenticate and how to redirect the requests.
Recently i came up with the need of re-routing, transforming and redirecting proxies. The idea behind it was how could i hide my real proxy behind another proxy by redirecting the requests over? or i could i setup a simple authentication method? In this article we will cover a few topics such as :
ContentsSection titled Contents
Glossary & InfoSection titled Glossary & Info
- Inbound Port — Port that we will accept the traffic FROM, this will be the port we typical use on our device ex: 192.168.111.2:8080
- Outbound Port — Port that we will redirect the traffic TO, this will be the port that we will redirect our traffic into.
- Inbound IP/Domain — The domain or IP used to receive the connections, again, this would be the IP or domain that we would use on our device that we want to use the proxy for.
- Outbound IP/Domain — Same as above, but outgoing, means this would be the ip or domain that will in fact receive or traffic.
{{outbound_port}}
or{{xxxx}}
those wildcards or placeholders will be replaced dynamically by an external script ( for example PHP str_replace ) with the ports and IPs we want.
DiagramSection titled Diagram
The following diagram shows an example of how we wanted it to look like. We didn’t wanted to expose our original proxy, so the idea is to create a masked proxy that will redirect our traffic to the real proxy.
Squid ( Formerly Squid-Cache )Section titled Squid ( Formerly Squid-Cache )
Squid is one of the most used and solid solutions when it comes to proxies. It allows you to create proxies, caching, authentication, user groups, and so on, I didn’t have time to explore it as a whole but at least is not done by Russians! hiihih ( joking ofc ).
Learn how to install Squid anywhere. Ex: Here
There is not much documentation or even examples online I could find about squid. But little i know squid relies on a single config file as shown below:
Squid Configuration TemplateSection titled Squid Configuration Template
Here is a sample of a squid configuration file, this is a simple example of how you could setup a proxy with squid, this is a simple example, you can find more about the configuration file here The only difference is this is a template, so laravel or any other language of your choice will replace the placeholders
header_replace Accept-Encoding gzip
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwd
auth_param basic credentialsttl 999 minutes
auth_param basic casesensitive on
auth_param basic realm easyshit
acl ncsa proxy_auth REQUIRED
follow_x_forwarded_for deny all
forwarded_for delete
via off
# Proxy Redirect Line
{{lines}}
# Squid Default Config
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access allow ncsa
coredump_dir /var/spool/squid
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern (Release|Packages(.gz)*)$ 0 20% 2880
refresh_pattern . 0 20% 4320
and here its the configuration for a single line ( proxy redirect line )
# Authentication for User with Port {{inbound_port}} with Reference #{{reference}}
# The user is being routed to {{outgoing_ip}}:{{outgoing_port}}
{{permissions}}
http_port {{inbound_port}} name=port_{{inbound_port}}
acl port_{{inbound_port}}_acl myportname port_{{inbound_port}}
always_direct deny port_{{inbound_port}}_acl
never_direct allow port_{{inbound_port}}_acl
cache_peer {{outgoing_ip}} parent {{outgoing_port}} 0 no-query {{outgoing_auth}} name=proxy{{inbound_port}}
cache_peer_access proxy{{inbound_port}} allow port_{{inbound_port}}_acl
cache_peer_access proxy{{inbound_port}} deny all
http_access allow localhost auth
More information could be found on Squid Documentation page, but i did find it confusing, so i went googling here and there to get this proper config. Thanks also to some of friends in proxies business that lend me a little help 🙂.
Please also keep in mind this configuration is already edited with some wildcards to be replaced later on.
3Proxy Configuration TemplateSection titled 3Proxy Configuration Template
Unlike Squid, 3proxy can have a simple bash running that will serve as our connection. A process in the machine will be alive and this will be the listener for our connections. In case we don’t want it any more we could just kill this process and our proxy/routing will be dead, this reduces a lot of overhead to manage connections. The first example is for HTTP to HTTP proxy and the second example will be from HTTP to Socks5, please once again keep in mind that there is wildcards represented with [object Object] that will be replaced with actual values, all this is done via PHP file.
You can find more details on how to install 3proxy on : https://github.com/SnoyIatK/3proxy
All we need to make sure is to run/kill this process to start/stop our proxy/routing.
#!/bin/bash
# Subscription: {{ $SUBSCRIPTION_REFERENCE }}
# Proxy: {{ $PROXY_REFERENCE }}
# Allocated port: {{ $ALLOCATED_PORT }}
# The user is being routed to {{ $ORIGINAL_HOST }}:{{ $ORIGINAL_PORT }}
daemon
pidfile /var/run/{{ $PID }}.pid
nserver {{ $PROXY3_DNS_1 }}
nserver {{ $PROXY3_DNS_2 }}
nscache 65536
nscache6 65536
timeouts 1 5 30 60 180 1800 15 60
deny * * 127.0.0.1,192.168.1.1
# Admin for this proxy, should be common for all users
auth strong
users {{ $PROXY3_ADMIN_USERNAME }}:CL:{{ $PROXY3_ADMIN_PASSWORD }}
allow {{ $PROXY3_ADMIN_USERNAME }} * * *
flush
# Build the user line
maxconn {{ $MAX_CONNECTIONS }}
auth strong
users {{ $ALLOCATED_USERNAME }}:CL:{{ $ALLOCATED_PASSWORD }}
allow {{ $ALLOCATED_USERNAME }} * {{ $ALLOWED_DOMAINS }} 80-88,8080-8088,443 HTTP,HTTPS
parent 1000 {{ $ORIGINAL_PROTOCOL }} {{ $ORIGINAL_HOST }} {{ $ORIGINAL_PORT }} {{ $ORIGINAL_USERNAME }} {{ $ORIGINAL_PASSWORD }}
proxy -4 -olSO_REUSEADDR,SO_REUSEPORT -ocTCP_TIMESTAMPS,TCP_NODELAY -osTCP_NODELAY -n -a -p{{ $ALLOCATED_PORT }}
flush
A small bash script can also be done to start the process automatically. The {{proxy3_bin}}
is the path to your 3proxy binary and the {{proxy_config}}
is the path to your .conf file ( mentioned above ), in this case we will also make sure to call Laravel Artisna command to verify the proxy is still valid, our backend will make sure to run the necessary commands to: delete the config file and terminate the process.
#!/bin/sh
if ps -aux | grep "3[p]roxy" | grep "{{proxy3_bin_grep}} {{proxy3_config}}" > /dev/null 2>&1;
then
echo 'Running {{reference}}';
else
{{proxy3_bin}} {{proxy3_config}} &
fi
/usr/bin/php -f {{artisan}} check:order {{reference}}
Squid & 3 Proxy Helper ClassSection titled Squid & 3 Proxy Helper Class
The following PHP Class is a just a helper iv created to automatically update/generate my config file on demand ( In this case from database ), this doesn’t work out of the box and will require more config to make it work, and obviously I’m not providing the whole code but just a proof of concept.
/**
* Replaces the keys and generates the user rules
*
* @return mixed
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
private function getProxyConfig(): string
{
$keys = [
# Inbound
'{{inbound_port}}' => $this->getInbound()->getPort(),
'{{inbound_username}}' => $this->getInbound()->getAuthUsername(),
'{{inbound_password}}' => $this->getInbound()->getAuthPassword(),
'{{inbound_allowed_urls}}' => '*', // Comma delimited instagram.com,*.instagram.com
# Outbound
'{{outgoing_ip}}' => $this->getOutbound()->getIpOrHostName(),
'{{outgoing_port}}' => $this->getOutbound()->getPort(),
'{{outgoing_protocol}}' => $this->getOutbound()->getProtocol(),
# Other
'{{pid}}' => random_number(100000, 10000000),
'{{max_connections}}' => 10000,
'{{name_server_1}}' => config('app.proxy3-dns-server-2'),
'{{name_server_2}}' => config('app.proxy3-dns-server-2'),
'{{reference}}' => $this->reference,
'{{admin_username}}' => config('app.proxy3-admin-username'),
'{{admin_password}}' => config('app.proxy3-admin-password'),
];
# Check if there is auth
if ($this->outbound->hasAuthentication() && $this->outbound->getAuth() !== null) {
$keys['{{outgoing_username}}'] = $this->outbound->getAuthUsername();
$keys['{{outgoing_password}}'] = $this->outbound->getAuthPassword();
} else {
$keys['{{outgoing_username}}'] = '';
$keys['{{outgoing_password}}'] = '';
}
if($this->inbound->getProtocol() === Parser::PROTOCOL_SOCKS5){
return replace($keys, self::getConfigTemplateSocks5());
}
return replace($keys, self::getConfigTemplate());
}
The result 🥳Section titled The result 🥳
Here is a small example of an internal app we have done in Laravel to manage all that, please keep in mind that some code might NOT be optimized as this is a demo project for the only propose of testing 3proxy and squid, feel free to make all the database logic, helpers, read the documentation deeper and if you have any questions feel free to ask!
Wrapping it up 👷♂️Section titled Wrapping it up 👷♂️
We have learned how to use squid & proxy config files ( more or less ), setup, and how it works, we have learned how to build a simple proxy redirecting using 3proxy from http -> http and http -> socks5, and how we can automate all this logic using a back-end ( Laravel & PHP ).
Proxies can be used for numerous reasons such as: to keep your connection safe, bypass blocked websites in your country, crawling, etc! If you liked this article please clap or comment bellow!