- Replace []net.Conn slice with context + atomic counter in activeTunnel
- Use errgroup.WithContext for pipe() to handle goroutine lifecycle
- Use context.AfterFunc to close connections on cancellation
- Fix race condition by comparing tunnel pointers instead of map lookup
- UpdateLocalSNIs now cancels tunnel context instead of iterating conns
This eliminates O(n) connection removal, prevents goroutine leaks,
and provides cleaner cancellation semantics.