An open API service indexing awesome lists of open source software.

https://github.com/o-x-l/proxy-forwarder

Service to forward traffic to a remote (Squid) proxy server (using NF-/IPTables)
https://github.com/o-x-l/proxy-forwarder

forward-proxy iptables nftables outbound-proxy proxy proxy-forwarder squid squid-proxy squid-proxy-server

Last synced: 6 days ago
JSON representation

Service to forward traffic to a remote (Squid) proxy server (using NF-/IPTables)

Awesome Lists containing this project

README

          

# Proxy Forwarder



Support Badge (Donate, Support-Licenses)

----

[![Test](https://github.com/O-X-L/proxy-forwarder/actions/workflows/test.yml/badge.svg?branch=latest)](https://github.com/O-X-L/proxy-forwarder/actions/workflows/test.yml)

This tool is specifically designed to solve a problem when using proxy servers:

* Setting the environment-variables 'HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy' and 'https_proxy' for all applications and HTTP-clients may be problematic/too inconsistent
* There is no clean way of forwarding all system traffic to a remote proxy server that is outside your layer 2 network
* Some proxy servers (_like Squid_) do not support redirecting the traffic using DNAT


Remote Proxy Server

For more information about Squid see: [OXL Docs - Squid](https://docs.o-x-l.com/proxy/forward_squid.html)

----

## How does it work?

This tool is based on [go-gost](https://gost.run/en/tutorials/redirect/) but was stripped of all features/dependencies that are unnecessary to perform this task.

### Support

* Layer 3: IPv4 & IPv6
* Layer 4: TCP
* Application: redirect of HTTP & HTTPS
* HTTP Versions: HTTP/1.0, HTTP/1.1, HTTP/2.0
* Target-Proxy Protocols: HTTP, HTTPS

### Usage

```bash
-P 'Listen port' (required)
-F 'Proxy server to forward the traffic to' (required, Example: 'http://192.168.0.1:3128')
-T 'Enable TProxy mode'
-M 'Mark to set for TProxy traffic' (default: None)
-V 'Show version'
-D 'Enable debug mode'
-U 'Enable UDP listeners'
-metrics 'Set a metrics service address (prometheus)' (Example: '127.0.0.1:9000', Docs: 'https://gost.run/en/tutorials/metrics/')
-no-log-time 'Do not add timestamp to logs' # use when systemd service
```

### It does

* Bind to localhost (_127.0.0.1 & ::1_) for TCP
* Allow you to redirect traffic to the forwarder using:

* Destination NAT (_default_)
* or [TProxy Mode](https://docs.kernel.org/networking/tproxy.html) (see also: [extended documentation](https://docs.o-x-l.com/firewall/nftables_tproxy.html#remote-proxy-problem))

* Forward the traffic to the server defined using the `-F` flag

These are the main two files that cover the logic:

* [redirect-tcp handler](https://github.com/superstes/proxy-forwarder/blob/latest/gost/x/handler/redirect/tcp/handler.go) (*HTTP/HTTPS split*)
* [http connector](https://github.com/superstes/proxy-forwarder/blob/latest/gost/x/connector/http/connector.go) (*CONNECT Tunnel*)

----

## Install

You can download the binary for most mainstream systems [from the releases](https://github.com/superstes/proxy-forwarder/releases)!

----

## Examples

```bash
> curl https://superstes.eu
# proxy-forwarder
2023-08-29 20:49:10 | INFO | handler | 192.168.11.104:36386 <=> superstes.eu:443/tcp | connection established
# squid
NONE_NONE/200 0 CONNECT superstes.eu:443 - HIER_NONE/- -
TCP_TUNNEL/200 6178 CONNECT superstes.eu:443 - HIER_DIRECT/superstes.eu -

> curl http://superstes.eu
# proxy-forwarder
2023-08-29 20:49:07 | INFO | handler | 192.168.11.104:50808 <=> superstes.eu:80/tcp | connection established
# squid
TCP_REFRESH_MODIFIED/301 477 GET http://superstes.eu/ - HIER_DIRECT/superstes.eu text/html
```

----

## Squid

This forwarder will connect:

* https over a HTTP-connect 'tunnel'
* plain http without such a 'tunnel'

So you need to make sure it is allowed by the proxy:

```text
acl CONNECT method CONNECT
acl ssl_ports port 443
acl step1 at_step SslBump1

http_access deny CONNECT !ssl_ports
http_access allow CONNECT step1
# NOTE: without 'step1' one would be able to create a CONNECT 'tunnel' through the proxy
```

----

## Redirect

### NFTables

Full example when using 'TProxy' mode: [NFTables - TProxy](https://gist.github.com/superstes/6b7ed764482e4a8a75334f269493ac2e)

```bash
# we expect you to have a table 'filter' of type 'inet'
sudo nft list ruleset

# whole input/forward traffic
sudo nft 'add chain inet filter prerouting_dnat { type nat hook prerouting priority -100; }'
sudo nft 'add rule inet filter prerouting_dnat tcp dport { 80, 443 } dnat to 127.0.0.1:3128'

# whole output traffic - excluding the traffic for the proxy-forwarder itself (anti-loop)
sudo nft 'add chain inet filter output_dnat { type nat hook output priority -100; }'
sudo nft 'add rule inet filter output_dnat tcp dport { 80, 443 } meta skuid != 1100 dnat to 127.0.0.1:3128'

# only output-traffic for one user to specific target (nice for testing purposes)
sudo nft 'add rule inet filter output_dnat meta l4proto tcp ip daddr 1.1.1.1 dnat to 127.0.0.1:3128'
sudo nft 'add rule inet filter output_dnat meta l4proto tcp ip6 daddr 2606:4700:4700::1111 dnat to [::1]:3128'
```

### IPTables

Full example when using 'TProxy' mode: [IPTables - TProxy](https://gist.github.com/superstes/c4fefbf403f61812abf89165d7bc4000)

```bash
# whole input/forward traffic
sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to-destination 127.0.0.1:3128
sudo iptables -t nat -I PREROUTING -p tcp --dport 443 -j DNAT --to-destination 127.0.0.1:3128

# whole output traffic - excluding the traffic for the proxy-forwarder itself (anti-loop)
sudo iptables -t nat -I OUTPUT -m owner ! --uid-owner 1100 -p tcp --dport 80 -j DNAT --to-destination 127.0.0.1:3128
sudo iptables -t nat -I OUTPUT -m owner ! --uid-owner 1100 -p tcp --dport 443 -j DNAT --to-destination 127.0.0.1:3128

# only output-traffic for one user to specific target (nice for testing purposes)
sudo iptables -t nat -I OUTPUT -m owner --uid-owner 1000 -d 135.181.170.219 -p tcp -j DNAT --to-destination 127.0.0.1:3128
```

----

## Permissions

### Destination NAT

If you use DNAT to redirect the traffic - the service user running the proxy-forwarder has no need for additional privileges!

A default linux user with `/usr/sbin/nologin` as shell is enough.

### TPROXY

If you want to use TPROXY to redirect the traffic - the service user needs the privilege to set `cap_net_raw` on its sockets.

The [CAP_NET_RAW](https://man7.org/linux/man-pages/man7/capabilities.7.html) may be needed for this:

> bind to any address for transparent proxying

You can add it like this:

```bash
setcap cap_net_raw=+ep /usr/local/bin/proxy-forwarder

# make sure only wanted users can execute the binary!
useradd proxy_forwarder --shell /usr/sbin/nologin
chown root:proxy_forwarder /usr/local/bin/proxy-forwarder
chmod 750 /usr/local/bin/proxy-forwarder
```

----

## Service

Here's an example systemd service to run the forwarder:

```text
# /etc/systemd/system/proxy-forwarder.service

[Unit]
Description=Proxy forwarder
Documentation=https://github.com/superstes/proxy-forwarder
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/proxy_forwarder -P 4128 -F http://192.168.1.20:3128 -no-log-time
User=proxy_forwarder
Group=proxy_forwarder
Restart=on-failure
RestartSec=5s

StandardOutput=journal
StandardError=journal
SyslogIdentifier=proxy_forwarder

[Install]
WantedBy=multi-user.target
```

----

## Build

* [Install go](https://go.dev/doc/install)
* Download this repository
* Build the binary

```bash
env GOOS=linux GOARCH=amd64 bash scripts/build.sh

# use 'CGO_ENABLED' if you see this error on the target system:
> error "/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32'"

env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 bash scripts/build.sh
```

* Copy the new binary to the target host(s)
* Run

```bash
proxy_forwarder -P 4138 -F http://192.168.10.20:3128
```