Skip to content
This repository has been archived by the owner on May 20, 2020. It is now read-only.

Force runtime to use custom Conn from netstack #29

Open
madman22 opened this issue Jul 26, 2019 · 9 comments
Open

Force runtime to use custom Conn from netstack #29

madman22 opened this issue Jul 26, 2019 · 9 comments

Comments

@madman22
Copy link

I'm getting tired of forking different golang projects to get them to use the conn interface from this project. Is there a way to get the runtime to always use a given netstack interface? Thanks!

@hbhasker
Copy link
Contributor

Not without hacking the go runtime.

@mjl-
Copy link

mjl- commented Aug 13, 2019

Are you aware of any project that does this? I.e. modify the "net" package to use netstack. I'm going to try doing that. But if it already exists, that would be even better.

@iangudger
Copy link
Contributor

I am pretty sure that it does not exist. We do have a package called gonet which creates net.Conn types backed by netstack.

@madman22
Copy link
Author

madman22 commented Aug 15, 2019

For example, I had to modify https://github.com/dutchcoders/goftp to be able to set a DialFunc which, if not nil, is called instead of the standard net Dial for the data transfer. The DialFunc is basically a wrapper for the gonet.DialTCP

Other packages like ssh are pretty easy since you can wrap it around an existing connection.

@mjl-
Copy link

mjl- commented Aug 16, 2019

I've got some really hacky proof of concept code that does tcp & udp using netstack. E.g. I can just have regular code with http.ListenAndServe or http.Get, and it works with a tun device.

I'm now configuring the stack through an env var GONET, setup with an init(), eg: GONET=ip=10.0.1.2,mtu=1500,sniff=yes.
Adding an ether=... makes it work on a tap device. I'm currently using fixed fd 3 (initialized by a calling process), but adding a dev=/dev/tun0 could make sense. If you preconfigure the interface, you could probably be done with only passing a path to a tun or tap device. There's probably already a standard way of passing this info...

The changes I made are currently part of more changes to the runtime, I'll see if I can isolate this, and make it less hacky.

Would be nice if building your code with a netstack buildtag would get you a netstack-based net package. The trick is finding the right (small) amount of changes to existing files in the net package that make this maintainable.

@mjl-
Copy link

mjl- commented Aug 24, 2019

Experimental code at https://github.com/mjl-/vmgo/tree/netstack, see README.

Summary: "go build -tags netstack app.go" followed by "GONET=...netconfig... ./app". Only on linux for now.

I've only done basic manual tests: net.Dial and net.Listen, and http.ListenAndServe and http.Get.

Some notes about netstack & gonet:

  • netstack has build tags to build some files for linux only. But it doesn't really compile on non-linux (and I can understand that isn't a goal and/or hasn't gotten attention). Tun/tap exists on most unixy platforms, should not be too hard to add. Some linux-specific backends can be stubbed out. I don't know if netstack (gvisor) is interested in making changes like that.
  • netstack uses golang.org/x/sys/unix, which depends on "net", which would create a cyclic dependency. I removed the dependency to get things moving. See master...mjl-:net.
  • The go toolchain checks strictly that no new dependencies to the std lib are added. I whitelisted netstack, and its dependencies. Netstack pulls in fmt, which pulls in more big packages. Not having those dependencies would be better.
  • I included gonet in "net", with previously exported names now prefixed with "gonet" and minor other modifications.

@hbhasker
Copy link
Contributor

@mjl- This is really neat! I was just checking out your project. I was reading the description and trying to understand what you are trying to do. The description just says
"WIP. goal: compiling existing Go code to standalone virtual machine images". Could you elaborate on what you are trying to do?

So netstack is mostly developed as part of gVisor and it's also used by Fuchsia. As a result most of the link layer code assumes linux as target and amd64 though we have recently been getting pull requests to add support run gVisor/Netstack on arm64/linux as well.

It should be possible to move these constants into platform specific bits in netstack and make most of the netstack code not use the unix package. If you would like you could send some of your changes as pull requests on gVisor repo and we can figure out a way to make this work.

This repo is mostly a read-only replica and we don't really accept contributions here.

@mjl-
Copy link

mjl- commented Aug 27, 2019

There's some more info in the README of the nofiles branch at https://github.com/mjl-/vmgo. My end-goal is to compile existing, unmodified Go code to a (slim) virtual machine image that runs on a simple monitor (solo5?, firecracker?, learning as I go...). My approach was to start with an existing target (openbsd/amd64) and trim away (replace with pure Go code) the functionality the OS provides, like the file system, the network stack. I was happily surprised to find netstack and see it work so well, thanks!

I'll have a look at gVisor and how to make changes there.

@iangudger
Copy link
Contributor

Super cool!

You may find more pieces you can use for your project in the gVisor repository. Its goal is to use Go to greatly reduce the host API surface required to run an unmodified Linux app.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants