yggdrasil-network / yggstack

Yggdrasil + Netstack (instead of TUN)
Other
26 stars 8 forks source link

lack of information about the address of the connected node when exposing tcp #2

Open jus7nyan opened 7 months ago

jus7nyan commented 7 months ago

I would like to somehow find out the IP of the connected node. As far as I understand, yggstack simply connects locally from 127.0.0.1 to the listening port. in this case, information about the address of the connected person is lost

jus7nyan commented 7 months ago

For example, you can not only connect yggstack to a port, but also send information about the public key of the connected node

jus7nyan commented 7 months ago

or expand the functionality of socks proxy and add the bind feature. I'm not sure that the socks5 protocol is responsible for informing about the client's address but that would be nice

basilgello commented 7 months ago

AFAIK the x-forwarded-for header is HTTP header. I need to check how to pass this imfo to generic TCP socket.

jus7nyan commented 7 months ago

The only thing I can think of is to simply send a package with the client's address. Doesn't look good, but I don't know how to do it better

jus7nyan commented 7 months ago

I’m not good at Go and so far I’ve added c2.Write([]byte(c1.RemoteAddr().String())) to the ProxyTCP function in the file src/types/tcpproxy.go

basilgello commented 7 months ago

Well, the key issue here is that the listening application must know how to handle this additional info. However, there is IP_PKTINFO structure that can attach exactly what you want to the socket. This still needs the target application to support this functionality, but at least it is documented. Windows also supports this structure.

jus7nyan commented 7 months ago

oh yeah of course I completely forgot. Is there really a sockopt field that can be used for this?

basilgello commented 7 months ago

Yup. https://man7.org/linux/man-pages/man7/ip.7.html states than PKTINFO is only for UDP sockets but IP_OPTIONS can be used for TCP or UDP. Not sure about Windows support of this header but 40 bytes can contain ipv6 address which you can map for the key.

basilgello commented 7 months ago

Also this gist shows how to set IP_OPTIONS before connect. We can use this approach with Yggdrasil or implement Proxy Protocol that Nginx, Apache etc do support.

basilgello commented 7 months ago

Also: https://github.com/cloudflare/mmproxy

basilgello commented 7 months ago

For sshd: https://github.com/tg123/sshpiper

basilgello commented 7 months ago

Or completely different single-binary SSH server implementation from GitLab; https://gitlab.com/gitlab-org/gitlab-shell/-/tree/main/internal/sshd

jus7nyan commented 7 months ago

what about socks proxy? If I'm not mistaken, the protocol describes the purpose (bind) of the TCP/IP port. but as I understand it, this is not implemented in yggstack. socks5 doesn't provide client ip either? and this might be more convenient than a command line argument. Is this necessary if the program cannot work through a proxy?

basilgello commented 7 months ago

From what I am reading about BIND SOCKS request, first the client sets primary SOCKS connection via CONNECT and then issues separate BIND request to make a second reverse tunnel. This is not equal to traditional bind/listen/accept used by server.

I think adding configurable Proxy Protocol support is best here. And the non-proxy aware apps can be made proxy-aware with library injection.

basilgello commented 7 months ago

The downside of the proxy protocol is that it does not allow re-using the same port for proxied and non-proxied connections simultaneously:

The receiver MUST NOT start processing the connection before it receives a
complete and valid PROXY protocol header. This is particularly important for
protocols where the receiver is expected to speak first (eg: SMTP, FTP or SSH).
The receiver may apply a short timeout and decide to abort the connection if
the protocol header is not seen within a few seconds (at least 3 seconds to
cover a TCP retransmit).

The receiver MUST be configured to only receive the protocol described in this
specification and MUST not try to guess whether the protocol header is present
or not. This means that the protocol explicitly prevents port sharing between
public and private access. Otherwise it would open a major security breach by
allowing untrusted parties to spoof their connection addresses. The receiver
SHOULD ensure proper access filtering so that only trusted proxies are allowed
to use this protocol.