xjasonlyu / tun2socks

tun2socks - powered by gVisor TCP/IP stack
https://github.com/xjasonlyu/tun2socks/wiki
GNU General Public License v3.0
2.85k stars 405 forks source link

Feature: support setSocketOptions on windows #192

Closed nange closed 1 year ago

nange commented 1 year ago

Hi, I have made a PR for supporting setSocketOptions on windows, since it is not supported now.

The idea is taken from wireguard-go

nange commented 1 year ago

It seems mistake that base on address parameter to exec bindSocketToInterface4 or bindSocketToInterface6 func. I think we should base on RawConn which is IPv4 or IPv6, but How can I know that? Do you have any suggestion? @xjasonlyu

xjasonlyu commented 1 year ago

Hi, thanks for the PR!

We don’t need RowConn to know whether is IPv4 or not. The network param already indicates that.

For example, in Darwin: https://github.com/xjasonlyu/tun2socks/blob/3cbc74b1cfc8be0fa60c747afbc8b9ad55557bf8/component/dialer/sockopt_darwin.go#L29-L34

nange commented 1 year ago

Hi, @xjasonlyu I have updated the code based on your suggestion. But I found it can't avoid routing loop with the code below:

pc, err := dialer.ListenPacketWithOptions("udp", "", &dialer.Options{
        InterfaceName:  mylocalName,
        InterfaceIndex: mylocalIndex,
})
if err != nil {
        // to do err
}

uAddr, _ := net.ResolveUDPAddr("udp", "114.114.114.114:53")
pc.WriteTo(mydata, uAddr)

Based on the code above, I found the network param in setSocketOptions will be udp6(actually my internet is "IPv4").

There are two ways to fix the routing loop issue that I found:

  1. use "udp4" in ListenPacketWithOptions func, eg.
        pc, err := dialer.ListenPacketWithOptions("udp4", "", &dialer.Options{
                InterfaceName:  mylocalName,
                InterfaceIndex: mylocalIndex,
        })
  2. only exec bindSocketToInterface4 in setSocketOptions func, eg.
    // ....
    if opts.InterfaceIndex != 0 {
        innerErr = bindSocketToInterface4(windows.Handle(fd), uint32(opts.InterfaceIndex))
    }
    // ....

I'm confused with the result. Any thought??

PS: I want to proxy all the system traffic except the target ip in China, so I need use dialer.ListenPacketWithOptions interface. And I also tested on MacOS, there is no routing loop issue although it has the similar code logic. My local env is: OS: Windows11, IP Net: IPv4

xjasonlyu commented 1 year ago

I guess it might have something to do with Windows' long ipv6 representing ipv4 addresses.

nange commented 1 year ago

Hi, @xjasonlyu please review the code again. I found a workaround to fix the routing loop issue on windows. I tested both on IPv4 and IPv6 network on windows11, it works correctly. But It's up to you to merge this PR, It's all ok for me.

xjasonlyu commented 1 year ago

I like this PR since I wondered how to solve routing loop issue on Windows before.

nange commented 1 year ago

@xjasonlyu Hi, replied to you. Please take a look.

xjasonlyu commented 1 year ago

Also, this feature is only supported on Windows 11, right?

nange commented 1 year ago

Also, this feature is only supported on Windows 11, right?

From the doc(https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options#windows-support-for-ip_proto-options), it doesn't support windows10 and lower. But I want to do a test on windows10 in Virtual Machine, I'll give you the result later.

xjasonlyu commented 1 year ago

Also, this feature is only supported on Windows 11, right?

From the doc(https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options#windows-support-for-ip_proto-options), it doesn't support windows10 and lower. But I want to do a test on windows10 in Virtual Machine, I'll give you the result later.

Ok, thanks. And let me know what happens actually, so we can discuss how to handle those circumstances.

nange commented 1 year ago

Also, this feature is only supported on Windows 11, right?

From the doc(https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options#windows-support-for-ip_proto-options), it doesn't support windows10 and lower. But I want to do a test on windows10 in Virtual Machine, I'll give you the result later.

I did the test on windows10 in Virtual Machine. I found it works fine on windows10 as well.

xjasonlyu commented 1 year ago

That's weird but OK.

nange commented 1 year ago

Hi, the style changes have been done.

xjasonlyu commented 1 year ago

Great, thank you for the PR and all the hard effort!

xjasonlyu commented 1 year ago

Hi, just to mention, someone has tested this feature under Windows 10 21H2 or below, but it doesn't seem to work.

nange commented 1 year ago

Hi, just to mention, someone has tested this feature under Windows 10 21H2 or below, but it doesn't seem to work.

That's weird. Could him open a issue? I want to know how to reproduce it.

xjasonlyu commented 1 year ago

I've had it tested, there's no problem. It turns out he misconfigured the interface name. 🤦‍♂️

e1732a364fed commented 1 year ago

很重要的功能 以及 对于 ipv4部分的 endian转换的发现!感谢