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

feat: support mieru protocol (issue #1563) (2nd attempt) #1697

Merged
merged 1 commit into from
Dec 9, 2024

Conversation

enfein
Copy link

@enfein enfein commented Dec 5, 2024

This is the second attempt to add mieru to mihomo.

The new mieru version resolved comments from #1574 about dialer proxy, concrete *net.TCPConn and *net.UDPConn types, and DNS resolver.

I created https://github.com/enfein/mieru/tree/main/test/deploy/mihomo to validate the change. Testing result can be found in test.txt. Also other people are confirming features are working enfein/mieru#172.

@wwqgtxx
Copy link
Collaborator

wwqgtxx commented Dec 5, 2024

Thanks for your contribution.

I have some confusion here: since Conn has been initiated on the mihomo side, why does mieruclient.Client still need to resolve the server's domain name?

@wwqgtxx
Copy link
Collaborator

wwqgtxx commented Dec 5, 2024

I read the source code of NewStreamUnderlay on mieru. If we add a separate dialer interface to mieru, just like in x/net/proxy

// A ContextDialer dials using a context.
type ContextDialer interface {
    DialContext(ctx context.Context, network, address string) (net.Conn, error)
}

Then perhaps we can set Dialer like setting Resolover for mieruclient.Client, so that Mieru.DialContext on mihomo can directly call DialContext of mieruclient.Client.

Client.DialContextWithConn could still be provided for DialContextWithDialer and StreamConnContext to call. If you think that keeping two sets of code on mieru side will increase the maintenance cost, you can directly remove this call path and delete SupportWithDialer at the same time. It will only affect the relay feature that has been marked as obsolete. dialer-proxy does not rely on these two functions)

Finally, the mux feature of mieru can be used normally without affecting dialer-proxy. There is no need to force it to MultiplexingLevel_MULTIPLEXING_OFF as in the current code.

@enfein
Copy link
Author

enfein commented Dec 5, 2024

Please correct me with the understanding:

  1. Either mihomo creates a net.Conn and pass it to mieruClient.DialContextWithConn, or mihomo provides a Dialer and let mieru to create the net.Conn as the part of mieruClient.DialContext. Using the Dialer is preferred because it can leverage the mux feature in mieru. The Dialer is per connection so it should be one parameter of mieruClient.DialContext instead of part of mieru configuration.
  2. If mieru server is a domain name, the DNS resolution is handled by the Dialer, so a Resolver is not required in mieru side.
  3. I only need to implement C.ProxyAdapter.DialContext. Implement C.ProxyAdapter.DialContextWithDialer and C.ProxyAdapter.SteamConnContext are optional.

@wwqgtxx
Copy link
Collaborator

wwqgtxx commented Dec 6, 2024

Most of your understanding should be correct, here are some small objections:

  1. Using Dialer as a parameter of mieruClient.DialContext may increase the complexity of mieru code, such as how to determine whether the incoming Dialer is the same as before, and how to deal with it if it is different. Therefore, it is recommended to use Dialer as the initialization property of mieruClient, just like http.Transport. The advantage is that in the future, the mux inside mieru can initiate reconnection by itself without relying on whether there is an external mieruClient.DialContext call.
  2. According to the current PR content, when only mieru's TCP mode is supported, Dialer can indeed handle domain name resolution problems by itself. However, considering that mieru also has UDP mode, it is still necessary to resolve the server's domain name to an IP address due to the WriteTo interface of net.PacketConn, so it may make sense to keep Resolver. (Of course, we can also use "connected udp socket" to rely only on the net.Conn interface, so that Dialer can still complete the domain name resolution work)
  3. Yes, the last two functions are optional. If you decide not to implement these two functions, then mieruClient.DialContextWithConn can also be omitted, which can avoid having two highly similar but non-reusable code chains in mieru.

@enfein
Copy link
Author

enfein commented Dec 8, 2024

Updated the PR based on previous feedback.

If it looks good but you don't like a rc version, I can create a new mieru release.

@wwqgtxx
Copy link
Collaborator

wwqgtxx commented Dec 8, 2024

The current PR should be close to perfect.

safeConnClose can be removed in DialContext, because no err will appear later, and naturally no conn needs to be closed.

As a complete PR, we still hope to have a dependency without an rc version number.

After these two modifications are completed, they will be merged directly.

@enfein
Copy link
Author

enfein commented Dec 9, 2024

done

@wwqgtxx wwqgtxx merged commit 508f6cf into MetaCubeX:Alpha Dec 9, 2024
55 checks passed
@wwqgtxx
Copy link
Collaborator

wwqgtxx commented Dec 9, 2024

Please downgrade the google.golang.org/protobuf to v1.34.2.

It will force set go version to 1.21. We need to maintain go1.20 compatibility.

The merge of this PR has been forcibly rolled back. Please open a new PR with this change, thanks.

@enfein
Copy link
Author

enfein commented Dec 9, 2024

Working on it.

@enfein enfein deleted the mieru branch December 9, 2024 04:08
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