tinyproxy / tinyproxy

tinyproxy - a light-weight HTTP/HTTPS proxy daemon for POSIX operating systems
GNU General Public License v2.0
4.8k stars 660 forks source link

When binding multiple IPv6 addresses, only the first one will be used as the outbound IP #526

Closed Rainscall closed 8 months ago

Rainscall commented 8 months ago

Tinyproxy version

State the tinyproxy version you're using; whether git master or 1.11.0 stable. tinyproxy 1.11.0

Issue

When binding multiple IPv6 addresses, only the first one will be used as the outbound IP My configuration file is like this

User tinyproxy
Group tinyproxy
Listen ::1
Port 3129
Bind 2605:6400:4222::1
Bind 2605:6400:4222::2
Bind 2605:6400:4222::3
Bind 2605:6400:4222::4
Timeout 60

In any case, only "2605:6400:4222::1" will be used, and the remaining other IPs will not work. Moreover, "2605:6400:4222::/48" has been routed to lo. Using "curl example.com --int 2605:6400:4222::1234" to bind the Outgoing IP can work normally.

rofl0r commented 8 months ago

In any case, only "2605:6400:4222::1" will be used, and the remaining other IPs will not work.

you mean connecting to them will not work, or as the title says the outcoming connection will come from ::1 ?

then the question becomes, what should happen ? is it expected an outgoing connection is being made from the address the incoming ip was bound to, or via the one set as default gateway in the kernel routing configuration ? and even if that is the agreed upon behaviour, how can it be implemented in a portable manner (i.e. not using linux-specific syscalls) ?

rofl0r commented 8 months ago

i just recalled there's the BindSame directive. from the manpage:

    BindSame
          If  this boolean parameter is set to `yes`, then Tinyproxy will bind
          the outgoing connection to the IP address of the incoming connection
          that triggered the outgoing request.

did you use that ?

Rainscall commented 8 months ago

In any case, only "2605:6400:4222::1" will be used, and the remaining other IPs will not work.

you mean connecting to them will not work, or as the title says the outcoming connection will come from ::1 ?

then the question becomes, what should happen ? is it expected an outgoing connection is being made from the address the incoming ip was bound to, or via the one set as default gateway in the kernel routing configuration ? and even if that is the agreed upon behaviour, how can it be implemented in a portable manner (i.e. not using linux-specific syscalls) ?

The incoming IP and outgoing IP are different. While the incoming one is ::1, the outgoing should be one of 2605:6400:4222::1, 2605:6400:4222::2, 2605:6400:4222::3, or 2605:6400:4222::4. Each request should use a different IP for the outbound connection.

However, in practice, only "2605:6400:4222::1" is used as the outbound IP, while the rest are not.

Here's an example of its usage:

# curl ip.sb ip.sb ip.sb -x [::1]:3129
2605:6400:4222::1
2605:6400:4222::1
2605:6400:4222::1

The desired outcome should be:

# curl ip.sb ip.sb ip.sb -x [::1]:3129
2605:6400:4222::3
2605:6400:4222::1
2605:6400:4222::2
rofl0r commented 8 months ago

ok, so you want to "round-robin" over your bound interfaces for outgoing connections. that functionality isn't available, but it shouldn't be too hard to implement. just check the code related to bindsame.doing it your way is kinda hackish though. it should be a single bound ip for listening, and some sort of new config directive to add outbound ips. either way i doubt it's of interest to many people.

Rainscall commented 8 months ago

ok, so you want to "round-robin" over your bound interfaces for outgoing connections. that functionality isn't available, but it shouldn't be too hard to implement. just check the code related to bindsame.doing it your way is kinda hackish though. it should be a single bound ip for listening, and some sort of new config directive to add outbound ips. either way i doubt it's of interest to many people.

I thought of a method, which might be: listen to [::]:3129, install an Nginx with stream and configure multiple Upstreams, for example:

server [2605:6400:4222::1]:3129;
server [2605:6400:4222::2]:3129;
server [2605:6400:4222::3]:3129;
server [2605:6400:4222::4]:3129;

Assuming Nginx is listening on [::1]:3456, the following command should work:

curl ip.sb ip.sb ip.sb -x [::1]:3456

Or perhaps make changes to SNAT in ip6tables?