ducaale / xh

Friendly and fast tool for sending HTTP requests
MIT License
5.6k stars 99 forks source link

Support for outbound interface selection #306

Closed fff7d1bc closed 1 year ago

fff7d1bc commented 1 year ago

Hi,

Would it be possible to add support for selecting outbound interface, much like curl's --interface option?

This would be useful on systems with multiple gateways, like multi WAN where there's more than single default gateway based on source address or when one uses opt-in VPN connections.

In my very case I have multiple wireguard VPNs connected at the same time with default gateway set in each separated routing tables, and simple set of ip rule add from $VPN1_IP table $VPN1_TABLE, that I use to test access to cloud resources from different physical location around the world. This is currently not possible directly with xh and requires me to have set of tinyproxy running in background each with different bind interface for xh to go via desired route. Would be great if I could just use --interface instead.

ducaale commented 1 year ago

What value would you like to pass to --interface? from cURL docs, I see that it accepts either interface name, IP address or host name.

We can add support for --interface <ip-address> by making use of ~reqwests's~ hyper's set_local_address. However, --interface <interface-name> is yet to be supported by hyper-rs. See https://github.com/hyperium/hyper/pull/3076 and https://github.com/seanmonstar/reqwest/issues/1336

fff7d1bc commented 1 year ago

I am okay with any of those. If I had option to choose I'd go with interface name, but setting the outbound local IP also works for me. iproute2 does have --json output so I can hack some script that I could use like xh --interface $(if-to-ip wg-relay4) .... that would just go over JSON from ip --json address show to figure out what local IP has the given interface, and return the IP.

The GNU wget also only supports binding to IP via --bind-address and have no smarts to specify interface instead, I think this is fully sufficient feature, though in this case perhaps --bind-address makes more sense than --interface as the switch unless you want later to add the interface selection, once those are supported by hyper bindings.

ducaale commented 1 year ago

I am leaning more towards mimicking cURL and only having the --interface option.

I can hack some script that I could use like xh --interface $(if-to-ip wg-relay4) .... that would just go over JSON from ip --json address show to figure out what local IP has the given interface, and return the IP.

Actually, we could let xh handle the interface to local IP mapping. Of course, this is a temporary solution since some users will sooner or later run into https://github.com/seanmonstar/reqwest/issues/1336.

ducaale commented 1 year ago

@slashbeast I would like to know if https://github.com/ducaale/xh/pull/307 works for your use case (CI is failing due to MSRV policy which we can ignore for now)

$ cargo run -- --interface wg-relay4 https://ipinfo.io/ip
fff7d1bc commented 1 year ago

All good, the build out of interface-option works exactly as I would expect curl --interface to work. Thanks for the feature!