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

refactor: modularize UDP connection handling #188

Closed
wants to merge 7 commits into from

Conversation

sbruens
Copy link

@sbruens sbruens commented Jun 26, 2024

Split the packet handler's Handle() method into 3 distinct parts for authentication, proxy request extraction, and proxy handling. This is similar to what was done with the TCP handler in #173.

There's more refactoring that can be done in future PRs, but this should make it easier to follow what's happening.

@sbruens sbruens force-pushed the sbruens/modularize-udp branch from 5707a9c to d74d1fd Compare June 26, 2024 22:04
@sbruens sbruens force-pushed the sbruens/modularize-udp branch from d74d1fd to bcf7e53 Compare June 26, 2024 22:06
@sbruens sbruens marked this pull request as ready for review June 26, 2024 22:07
@sbruens sbruens requested a review from a team as a code owner June 26, 2024 22:07
@sbruens sbruens requested review from fortuna and jyyi1 June 27, 2024 14:58
@sbruens sbruens marked this pull request as draft June 28, 2024 00:13
@sbruens sbruens removed request for a team, fortuna and jyyi1 June 28, 2024 00:13
@sbruens sbruens force-pushed the sbruens/modularize-udp branch from 32f9df0 to 7ab36b2 Compare June 28, 2024 19:19
@sbruens sbruens marked this pull request as ready for review June 28, 2024 19:26
@sbruens sbruens requested review from fortuna, jyyi1 and a team June 28, 2024 19:27
Copy link

@fortuna fortuna left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UDP is complicated. We need more elaborate encapsulation to actually make the UDP handling protocol-agnostic. If you look at the TCP code, the only place we refer to the shadowsocks package is in the authenticate method. That is not the case here, where we still have references to shadowsocks in multiple places, so the PR is not accomplishing the goal of encapsulating the protocol. I also think there are some correctness issues.

Let's brainstorm more about it. We will need some concept of authenticated "PacketConn" that is tied to the NAT, but we also need to keep the NAT logic separate from the protocol.

@@ -35,7 +36,7 @@ type UDPMetrics interface {
ipinfo.IPInfoMap

// UDP metrics
AddUDPPacketFromClient(clientInfo ipinfo.IPInfo, accessKey, status string, clientProxyBytes, proxyTargetBytes int)
AddUDPPacketFromClient(clientInfo ipinfo.IPInfo, accessKey, status string, data metrics.ProxyMetrics)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API is broader than needed. Why pass the bytes from the target?

It also adds an unnecessary dependency on github.com/Jigsaw-Code/outline-ss-server/service/metrics.

}
}()
func (h *packetHandler) authenticate(clientConn net.PacketConn) (net.Addr, *CipherEntry, []byte, int, *onet.ConnectionError) {
cipherBuf := make([]byte, serverUDPBufferSize)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is changing from a single allocation for the port, to an allocation per packet. The single allocation was intentional. Every per-packet allocation accelerates memory growth, reducing performance and causing crashes, in particular on iOS, but also Android.

Can we keep the single allocation? Having a benchmark would also help.

}
}
func (h *packetHandler) handleConnection(clientConn net.PacketConn) (string, ipinfo.IPInfo, metrics.ProxyMetrics, *onet.ConnectionError) {
defer func() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this to the caller for loop, so it's better encapsulated.

return onetErr
}
unpackStart := time.Now()
cipherEntry, textData, keyErr := findAccessKeyUDP(remoteIP, textBuf, cipherBuf[:clientProxyBytes], h.ciphers)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must lookup the NAT table first, before you do the cipher search.

@sbruens sbruens closed this Jul 23, 2024
@sbruens sbruens deleted the sbruens/modularize-udp branch November 22, 2024 18:39
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.

2 participants