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

net: expose a way to inject a function after fd created before connect/listen #21820

Closed
ayanamist opened this issue Sep 9, 2017 · 7 comments
Closed

Comments

@ayanamist
Copy link

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.9 windows/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

set GOARCH=arm64
set GOBIN=
set GOEXE=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=android
set GOPATH=C:\Users\ayanamist\Documents\Projects\gopath
set GORACE=
set GOROOT=C:\Go
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=C:\Users\ayanamist\AppData\Local\Android\sdk\ndk-root\bin\aarch64-linux-android-clang.cmd
set GOGCCFLAGS=-fPIC -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\AYANAM~1\AppData\Local\Temp\go-build570635583=/tmp/go-build -gno-record-gcc-switches
set CXX=g++
set CGO_ENABLED=1
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config

What did you do?

I'm writing an Android VPN app using VPNService with golang, and want to use protect method to let socket created by golang executables bypass vpn.
I have done a bridge to pass socket fd from golang to java, but i found this can not work, because protect method using fwmark to work, and it requires protect invoked before connect/listen.
All socket fds bundles fd creation and connect/listen, so we need a method to use protect after fd create before connect/listen.
Currently, i forked golang and add a setter in net/hook_unix.go which make socketFunc settable.
Also i found another project shadowsocks-android use similar method shadowsocks@5eb4737

What did you expect to see?

Provide a method to hook between fd creation and socket connect/listen

What did you see instead?

@ianlancetaylor
Copy link
Contributor

I believe you can do this by calling syscall.Socket to get a socket, doing whatever you like to the socket, then calling syscall.Connect, then os.NewFile to convert the socket descriptor into an os.File, then net.FileConn to convert the os.File into a net.Conn. Certainly awkward, but it's not clear that we want to complicate the net package by inserting hooks that can run arbitrary code.

@ayanamist
Copy link
Author

ayanamist commented Sep 9, 2017

@ianlancetaylor I have considered your solution before, but after i read all codes related to connect/listen, i found what you said is quite complicated.
For example, tcp and udp have quite different implementation after fd creation.
I have to copy nearly all net related codes to implement what you said.

Now i create a new file hook_android.go under $GOROOT/src/net with

package net

func SetSocketFunc(f func(int, int, int) (int, error)) {
	socketFunc = f
}

So i can reuse all codes, and inject my function in a init function.

Can you provide similar solution?

@ianlancetaylor
Copy link
Contributor

I think that solution is more or less a non-starter. It's only going to work where you know that no init code creates a socket and where you know exactly which sockets are created.

More plausible would be code in golang.org/x/net that does what I already suggested. It only has to be written once.

@ayanamist
Copy link
Author

where you know exactly which sockets are created

No, i don't need to distinguish this, all outgoing sockets need this "protect".

And init code creates a socket is rare.

Copy nearly all existing net code to golang.org/x/net with only one hook function different? I think it's more difficult to maintain.

@ianlancetaylor
Copy link
Contributor

We don't need to copy all existing net code to golang.org/x/net. We only need the code needed to initialize a socket.

I understand that the hook can fix your specific problem. I'm questioning whether it is a general solution. And the API of the net package is already too complex.

@ayanamist
Copy link
Author

It's a Android-specific issue, because in other situation, we can pre-configure iptables rules to apply fwmark for all new connections. Only Android non-root VPNService implementation make things complicated, so i suggest use "_android" suffix to limit this API to android only.

@mikioh
Copy link
Contributor

mikioh commented Dec 1, 2017

Dup of #9661.

@mikioh mikioh closed this as completed Dec 1, 2017
@golang golang locked and limited conversation to collaborators Dec 1, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants