koro666 / xsocket

Cross-namespace socket library
2 stars 0 forks source link

[Question] Is it possible to create a xbind wrapper for applications? #2

Open alpominth opened 1 month ago

alpominth commented 1 month ago

I would like to use libxbind.so with some programs but I can't, because Go programs doesn't work with LD_PRELOAD trick.

Is it possible to create an applications wrapper that can work with these kind of executables and also static ones? Something like

koro666 commented 1 month ago

It could be doable with a heavy-handed approach like ptrace to intercept the socket system call and handle it out-of-process, but I think such an approach would tank performance.

proot already implements this approach in a generic way, and would likely be possible to modify its socket system call handling to call xsocket and swap the file descriptor.

However, at this point, it seems simpler to just recompile the static binary instead.

alpominth commented 1 month ago

@koro666

ptrace is the first thing that comes to my mind in this case.

I've seen a project that implements remapping of ports using ptrace(): https://github.com/mildred/force-bind-seccomp

However, at this point, it seems simpler to just recompile the static binary instead.

I understand, however Go compiled programs, even dynamically compiled, doesn't work with LD_PRELOAD. The lists of applications and tools that are written in Go is extensive.

I'm just using xsocket with Tor, works magically.


Thanks.

alpominth commented 1 month ago

@koro666

"Upon reception of such a message, the server creates the requested socket, then passes it back using SCM_RIGHTS to the client. In case of failure, an error code is returned instead."

Just for curiosity, is it possible to do the opposite of what xsocket does actually? I mean, to listen in a namespace and connect to the network of another one instead of just listen.

If it is possible, a very good idea is to implement this feature, it would rocks.

koro666 commented 1 month ago

I understand, however Go compiled programs, even dynamically compiled, doesn't work with LD_PRELOAD. The lists of applications and tools that are written in Go is extensive.

The xsocket protocol is simple enough that a pure Go client could easily be written. It's basically just marshalling the socket parameters and getting the file descriptor or errno back.

I'm just using xsocket with Tor, works magically.

Just remember that there is no security. Hopefully you are using xsocket to bind the Tor SOCKS port inside an empty namespace, and not the opposite. Otherwise, anything from inside the namespace could just create a socket and connect out.

Just for curiosity, is it possible to do the opposite of what xsocket does actually? I mean, to listen in a namespace and connect to the network of another one instead of just listen.

It's already possible to connect out using a socket returned by xsocket. You can link with libxsocket.so and call xsocket inside. There is not just no LD_PRELOAD wrapper provided because I don't see the point: if you want to connect out from another namespace, then there is not much point in being in a separate namespace to begin with.

alpominth commented 2 weeks ago

@koro666

There is not just no LD_PRELOAD wrapper provided because I don't see the point: if you want to connect out from another namespace, then there is not much point in being in a separate namespace to begin with.

I think that implementing an option to send the outgoing connection to the netns in which xsocket-server is active is a good idea.

Some use cases:

The option could be: XCONNECT=0|1

Like this: LD_PRELOAD="/path/to/libxbind.so /path/to/libxsocket.so" XBIND="1080 3128" XCONNECT="1" XSOCKET="/tmp/foo" /usr/local/bin/proxy_server <args>

alpominth commented 1 week ago

@koro666

Just remember that there is no security.

Maybe implementing password protection in the unix socket of xsocket-server could address the issue.

koro666 commented 2 days ago

I think that implementing an option to send the outgoing connection to the netns in which xsocket-server is active is a good idea.

I've recently come across a use-case where having had such a feature would have saved me some time, so I'll consider the option. However, this would need a great deal of refactoring to do it right, so I'll do this... eventually.

For my particular issue, I managed to "turn it around" by telling curl to explicitly bind before connecting:

LD_PRELOAD=libxbind.so XBIND=1234 curl --local-port 1234 https://...

Maybe implementing password protection in the unix socket of xsocket-server could address the issue.

Security is hard to get right, which is why I did not want to implement any. If I implement security and there is a flaw, then it's my fault.

A netns with a VPN connection is configured, xsocket-server is listening with an unix socket in the netns, a SOCKS5 server send its outgoing connection over the VPN netns and listen its ports on the host side, so providing a SOCKS5 proxy for the applications running in the host network side.

This particular use case could be done by having the SOCKS5 proxy run inside the netns, and using xbind to bind its SOCKS5 port in the main namespace.

alpominth commented 1 day ago

I've recently come across a use-case where having had such a feature would have saved me some time, so I'll consider the option. However, this would need a great deal of refactoring to do it right, so I'll do this... eventually.

For my particular issue, I managed to "turn it around" by telling curl to explicitly bind before connecting:

LD_PRELOAD=libxbind.so XBIND=1234 curl --local-port 1234 https://...

It's could be done by intercepting connect() syscall after the socket closing in the actual netns and re-opening a socket in the target netns, and so letting the connect() flow in the targert netns.

You could create a library called "libxconnect" apart from libxbind, it would work with xsocket-server. I think it wouldn't require refactoring the stuff.

I tested the curl trick you posted, but I couldn't make Tor and 3proxy (SOCKS5 server) work with it.

Security is hard to get right, which is why I did not want to implement any. If I implement security and there is a flaw, then it's my fault.

I understand.

This particular use case could be done by having the SOCKS5 proxy run inside the netns, and using xbind to bind its SOCKS5 port in the main namespace.

I know this works, but I said that because the majority of SOCKS servers doesn't work with libxbind when using UDP, that is because of a particularity of most SOCKS5 servers, the SOCKS5 servers open UDP ports dynamically, it could be any port number, and libxbind doesn't intercept them:

See this thread of my friend: https://github.com/3proxy/3proxy/issues/1044#issuecomment-2178270085