Closed jungle-boogie closed 7 years ago
I've been tinkering with this since I believe the ability to force hping to use IPv4/IPv6 would be a great addition to it.
The problem is that golangs http client can't (at least from my investigation) be forced to use IPv4/IPv6 easily. From my understanding there are two ways to solve this:
Do some magic with Dial and force which IP-version that should be used. It doesn't seem to be very straight forward tho.
Leverage the fact that before the actual requests are sent, mylg resolves the hostname. I'm thinking a setup like this: hping resolves the address with the specified IP-version (if no version is specified; use the default happy eyeballs setup) and then when the requests are sent, send them against the IP-address instead but specify a Host-header with the hostname so that the receiving webbserver knows which site is requested.
I'm leaning towards the second setup but it feels a bit.. icky. What are your thoughts on this, @mehrdadrad? Do you know of a better way to solve this or have I misunderstood something about golangs http client and its easy to specify the IP-version?
I checked on the #go-nuts IRC channel. Perhaps this is clear to you two:
So net.Dial gives you a net.Conn, you put the net.Conn in the http.Transport, you put the http.Transport in the http.Client
@gummiboll I didn't try it yet but may it works once we resolved to specific IP address
http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
addr = net.JoinHostPort(ipAddress, port)
return dialer.DialContext(ctx, network, addr)
}
another suggestion from Golang slack channel
t := &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
if conn, err := net.Dial("tcp6", addr); err == nil {
return conn, nil
}
return net.Dial("tcp", addr)
},
}
c := &http.Client{
Transport: t,
}
That seems quite clean. Will fiddle a little with it and make a PR. :)
PR submitted.
However, note the issue mentioned in it about happy eyeballs. I.e; since mylg first resolves the ip-address of the hostname and then again when it does the actual requests it can cause a issue where you think its pinging the IPv4-address but instead it pings the IPv6-address or the other way around. From testing this it seems like ResolveIPAddr
prefers IPv4 over IPv6 but I haven't read through the sorce for ResolveIPAddr
so I can be wrong.
As I see it, there is a couple of ways to handle this:
ResolveIPAddr
prefering IPv4 this is essentially the same as forcing IPv4.@gummiboll How about this:
+ 316 DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+ 317 if r := strings.Index(p.rAddr.String(), ":"); r != -1 {
+ 318 return net.Dial("tcp6", addr)
+ 319 }
+ 320 return net.Dial("tcp4", addr)
+ 321 },
I was thinking something like:
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
if p.rAddr.To4() != nil {
return net.Dial("tcp4", addr)
} else {
return net.Dial("tcp6", addr)
}
}
but will investigate however ResolveIPAddr
prefers ipv4 or not first.
type net.Addr doesn't have To4 as net.IP does. anyway, same solution. Thanks for investigating
Ah, yeah - that's correct. So either change rAddr to net.IP or do a strings.Index. I kinda like the .To4()-solution better, looks cleaner but doesn't really matter. Both works. :)
If I read this correctly it seems like ResolveIPAddr
does prefer ipv4 and from testing it seems to always return the ipv4-address but that kinda feels.. weird.
@gummiboll check the myLG->ping how it works, if IPv6 available on the client and name server then it tries to use IPv6 but if IPv6 not available on the client or name server then it tries to use IPv4. it think this login is make sense. what do you think?
@gummiboll, @mehrdadrad, I think something is missing:
-4 Force IPv4
-6 Force IPv6
hping -6 scanme.nmap.com
and even hping -4 scanme.nmap.com
return the help for hping
.
@jungle-boogie usage: hping url [options] try hping scanme.nmap.com -6
@mehrdadrad: Will fiddle and try to come up with a good solution and make a pr when done.
thanks for implementing this!
Hi,
From looking at the
hping
options, it doesn't seem there's an option to connect via ipv6: