go-gost / gost

GO Simple Tunnel - a simple tunnel written in golang
https://gost.run
MIT License
3.7k stars 465 forks source link

Bind to outgoing interface? #354

Open s3rj1k opened 7 months ago

s3rj1k commented 7 months ago

I am looking for the ability to set specific outgoing interface while doing -L proxying.

The idea is simple, multiple different listen ports and each one has different "default gateway".

So custom routing rules or manual restriction on outgoing interface can be a solution.

Why it is needed, basically having multiple VPN interfaces I want to proxy all incoming traffic of one listener into VPN tunnel and for second new listener to another.

Can some one suggest how can this be done?

alpominth commented 4 weeks ago

$ gost -L "socks5://username:password@127.0.0.1:1080?interface=tun0&udp=true" -L "http://127.0.0.1:3128?interface=eth0" -L "gost -L http+h3://127.0.0.1:3128?interface=eth0"

tun0 = VPN tunnel interface eth0 = Network ethernet interface

You can also specify IP addresses with "interface=", but you may choose either an IPv4 or IPv6 address, not the two types at same time, maybe "interface=" when used with IP addresses should be renamed to "bind4" and "bind6" by the devs of this project, allowing to use them two times for both IPv4 and IPv6 connectivity.

s3rj1k commented 1 week ago

-L "gost -L http+h3://127.0.0.1:3128?interface=eth0"

I think this is invalid.

My problem was that default route was not respected via tunnel, but context is lost already sadly.

alpominth commented 1 week ago

Maybe you should add fwmarks and additional routing tables for each interface, if you couldn't make GOST work with default routes of specific interface.

For eth0:

ip -4 route show dev eth0 table unspec | while read line; do
  ip -4 route add ${line} dev eth0 table 10
done
ip -4 rule add fwmark 10 table 10

ip -6 route show dev eth0 table unspec | while read line; do
  ip -6 route add ${line} dev eth0 table 10
done
ip -6 rule add fwmark 10 table 10

For tun0:

ip -4 route show dev tun0 table unspec | while read line; do
  ip -4 route add ${line} dev tun0 table 11
done
ip -4 rule add fwmark 11 table 11

ip -6 route show dev tun0 table unspec | while read line; do
  ip -6 route add ${line} dev tun0 table 11
done
ip -6 rule add fwmark 11 table 11

eth0 = 10, tun = 11

===

If the interfaces have IPs, but don't have default routes, you'll need to add them manually:

ip -4 route add default via <gateway_addr> dev eth0 table 10
ip -6 route add default via <gateway_addr> dev eth0 table 10
ip -4 route add default via <gateway_addr> dev tun0 table 11
ip -6 route add default via <gateway_addr> dev tun0 table 11

For Wireguard and OpenVPN tunnel interfaces, you can omit {via } (maybe SSTP tunnels should work too):

ip -4 route add default dev eth0 table 10
ip -6 route add default dev eth0 table 10
ip -4 route add default dev tun0 table 11
ip -6 route add default dev tun0 table 11

===

After setting up the fwmarks and tables, point GOST to them:

$ gost -L "socks5://username:password@127.0.0.1:1080?so_mark=10&udp=true" -L "http://127.0.0.1:3128?so_mark=11" -L "gost -L http+h3://127.0.0.1:3128?so_mark=11"

SOCKS5 will use fwmark 10 of device eth0 and http+http3 will use the fwmark 11 of device tun0

s3rj1k commented 1 week ago

Wow, that's nice, I was fine with using one binary per exit interface but that could actually work very nicely.

IMO, should be added in docs

alpominth commented 6 days ago

I created a tiny script for creating fwmarks an routing tables for network interfaces: https://gist.github.com/alpominth/1314be7da682b13277241ceaf0ed9417

This script create two default routes:

ip -4 route add blackhole default table ${TABLE} metric 9999 ip -4 route add ${line} dev ${IFACE} table ${TABLE} metric 95

It will prevent ip leaking to other interfaces, even if the interface goes down.