Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macos routes #49

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Macos routes #49

wants to merge 9 commits into from

Conversation

lsgrep
Copy link

@lsgrep lsgrep commented Apr 13, 2024

Thanks a lot for creating this. Here is how i am using this on macOS. It is pretty ugly (without syscall), but it might help out the if someone want to use this in macOS. It is working for me. I am just sharing my solution, rather than hoping getting it merged into the codebase.

@alexander-potemkin
Copy link

@database64128 could this be merged into the main source code tree? Or any additional things needs to be done?
I would love to see clean MacOS implementation, if possible!

@database64128
Copy link
Owner

@alexander-potemkin No, like the author said, this is too much of a hack to be merged.

If your internet-facing physical interface has a fixed IP address, like 192.168.50.11, you could specify "proxyConnListenAddress": "192.168.50.11:" in your client config to let swgp-go bind to 192.168.50.11:0 for its outgoing sockets.

@database64128
Copy link
Owner

@lsgrep Off-topic shameless plug: Saw you wrote https://github.com/lsgrep/cfbind, thought you might be interested in a similar project of mine: https://github.com/database64128/ddns-go. On Linux and Windows, ddns-go can use native platform APIs to monitor network interface address changes, without the need of polling at a fixed interval.

@lsgrep
Copy link
Author

lsgrep commented Dec 18, 2024

If your internet-facing physical interface has a fixed IP address, like 192.168.50.11, you could specify "proxyConnListenAddress": "192.168.50.11:" in your client config to let swgp-go bind to 192.168.50.11:0 for its outgoing sockets.

I move around a lot with laptop and sometimes I use mobile hotspot so fixed IP does not work for me.

@database64128
Copy link
Owner

I move around a lot with laptop and sometimes I use mobile hotspot so fixed IP does not work for me.

Does the network interface change? Would it work for you if I add an option to bind to a specific interface?

@database64128
Copy link
Owner

Thank you for rebasing and keeping this PR up-to-date! It's in much better shape now that the route calls are implemented in code. Still, I have some concerns with the approach taken here. Polling for route changes will always leave room for routing loops in between polls. Instead of relying on the OS routing table, may I suggest another approach?

Currently, swgp-go implements sticky sockets at the "listener" end. That is, it remembers the last network interface and IP the client packet was received from, and always sends back via the same path. The facility for implementing this is well abstracted, and can be used for the outgoing end as well.

swgp-go/service/client.go

Lines 649 to 651 in 8c4f6a1

scm := conn.SocketControlMessage{
SegmentSize: sqp.segmentSize,
}

Your "default gateway" (or whatever you call it) service could maintain an atomic pointer to the current outgoing network interface index and IP address, and in the above code snippet, populate the relevant fields in conn.SocketControlMessage, something like:

if c.autoOutgoingIface {
	if info := outgoingIfaceState.Load(); info != nil {
		scm.PktinfoAddr = info.Addr
		scm.PktinfoIfindex = info.Ifindex
	}
}

@lsgrep
Copy link
Author

lsgrep commented Dec 22, 2024

Does the network interface change? Would it work for you if I add an option to bind to a specific interface?

I can fix the IP address, but this may cause problems as I switch to new network the range might not be totally different from what I've setup on my machine. And There could be some IP address conflict even if the network range is the same.

@lsgrep
Copy link
Author

lsgrep commented Dec 22, 2024

Currently, swgp-go implements sticky sockets at the "listener" end. That is, it remembers the last network interface and IP the client packet was received from, and always sends back via the same path. The facility for implementing this is well abstracted, and can be used for the outgoing end as well.

Please correct me If I am wrong, I am assuming that this approach assumes that we could get to send out packets successfully and we get to parse the control message out from the received packets?

Current problem I am facing is that when swgp (default version) and wireguard are running, I could not send out any packets as the routing is not correctly setup for macOS. There is a loop and all the traffic goes to wg.

I've been using the new deployed code on my machine it is working great. I could not see any issues so far.

@database64128
Copy link
Owner

Does the network interface change? Would it work for you if I add an option to bind to a specific interface?

I can fix the IP address, but this may cause problems as I switch to new network the range might not be totally different from what I've setup on my machine. And There could be some IP address conflict even if the network range is the same.

I'm not asking you to use a fixed IP address. I'm asking whether the physical interface in use changes between places. For example, when you switch to a mobile hotspot, is the physical interface still en0?

@database64128
Copy link
Owner

Please correct me If I am wrong, I am assuming that this approach assumes that we could get to send out packets successfully and we get to parse the control message out from the received packets?

No, that's not what I meant. Your current approach is to discover the default physical interface and add a route to the swgp-go server address via the interface's gateway. What I'm saying is, instead of using the information to create routes, you could simply set the pktinfo on outgoing packets so they are sent via the right physical interface.

@lsgrep
Copy link
Author

lsgrep commented Dec 23, 2024

I'm not asking you to use a fixed IP address. I'm asking whether the physical interface in use changes between places. For example, when you switch to a mobile hotspot, is the physical interface still en0?

Yes. will be fixed for most of the time. en0

@lsgrep
Copy link
Author

lsgrep commented Dec 23, 2024

No, that's not what I meant. Your current approach is to discover the default physical interface and add a route to the swgp-go server address via the interface's gateway. What I'm saying is, instead of using the information to create routes, you could simply set the pktinfo on outgoing packets so they are sent via the right physical interface.

I surely can set the pktinfo via the socket control message, but it still cannot solve no route problem ? I mean specifying the outgoing networking interface is not enough not send the packet out if there is not route?

@database64128
Copy link
Owner

database64128 commented Dec 23, 2024

I surely can set the pktinfo via the socket control message, but it still cannot solve no route problem ? I mean specifying the outgoing networking interface is not enough not send the packet out if there is not route?

What's this no route problem? Isn't there a default route for the physical interface?

It should be easy to verify whether my approach works or not.

swgp-go/service/client.go

Lines 649 to 651 in 8c4f6a1

scm := conn.SocketControlMessage{
SegmentSize: sqp.segmentSize,
}

Just hardcode the PktinfoAddr and PktinfoIfindex fields here and see if it works.

@lsgrep
Copy link
Author

lsgrep commented Dec 23, 2024

Actually I tried this, it threw routing errors (could not route to the proxy server). It did not work.

https://github.com/lsgrep/swgp-go/tree/macos-routes2

@database64128
Copy link
Owner

Actually I tried this, it threw routing errors (could not route to the proxy server). It did not work.

https://github.com/lsgrep/swgp-go/tree/macos-routes2

Sorry I didn't describe it clearly. The PktinfoAddr needs to be the network interface's IP address, not the gateway address. Say your assigned IPv4 address on en0 is 192.168.1.5/24, you set PktinfoAddr to 192.168.1.5, not 192.168.1.1.

@lsgrep
Copy link
Author

lsgrep commented Dec 23, 2024

I also tried that as well, it also did not work.

@lsgrep
Copy link
Author

lsgrep commented Dec 23, 2024

I also could not wrap my head around the networking, without the route how networking interface could send the packet out? Sorry this might be a dumb question

@lsgrep
Copy link
Author

lsgrep commented Dec 23, 2024

Dec 23 21:49:30.393 WRN Failed to write swgpPacket to proxyConn client=client-mac listenAddress=[::]:23456 clientAddress=[::ffff:127.0.0.1]:51820 proxyConnListenAddress=192.168.1.4:60100 pr
oxyAddress=PROXY_SERVER:20221 swgpPacketLength=1229 segmentSize=1229 err="write udp4 192.168.1.4:60100->PROXY_SERVER:20221: sendmsg: no route to host"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants