- Notifications
You must be signed in to change notification settings - Fork1k
chore: implement CoderVPN client & tunnel#15612
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
ethanndickson commentedNov 21, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
This stack of pull requests is managed byGraphite. Learn more aboutstacking. |
stringapi_token=3; | ||
// Additional HTTP headers added to all requests | ||
messageHeader { | ||
stringname=1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Deliberately not a map to support repeated headers
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
"github.com/coder/coder/v2/vpn" | ||
) | ||
funcTestClient_WorkspaceUpdates(t*testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This test might be a bit much, but I wanted to test the Client without spinning up a wholecoderd
, and it turns out that takes a bit of code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This is a lot. Is there any particular reason to not spin up coderd (other than wanting to be lean I guess) to avoid all this boilerplate?
Uh oh!
There was an error while loading.Please reload this page.
typeConninterface { | ||
CurrentWorkspaceState()*proto.WorkspaceUpdate | ||
Close()error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I suspect this interface will grow with whatever functions fromtailnet.Conn
we end up needing.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
vpn/tunnel.go Outdated
fori,agent:=rangeupdate.UpsertedAgents { | ||
out.UpsertedAgents[i]=&Agent{ | ||
Id:agent.Id, | ||
Name:agent.Name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
missing workspace_id, fqdn.
Also missing ip address and last handshake, but we can save those for another PR.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
// TODO: Wait for the reply to be sent before closing the speaker. | ||
// err := t.speaker.Close() | ||
// if err != nil { | ||
// t.logger.Error(t.ctx, "failed to close speaker", slog.Error(err)) | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I think our tunnel may need a mutex or sync.Once to handle being closed properly?
ifoptions.TUNDev==nil { | ||
dialer.NetstackDialTCP=func(ctx context.Context,dst netip.AddrPort) (net.Conn,error) { | ||
returnnetStack.DialContextTCP(ctx,dst) | ||
} | ||
netStack.ProcessLocalIPs=true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Can we consolidate the places we do this check onoptions.TUNDev
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I'm not sure if changing some of the ordering here breaks anything, may need to revisit cleaning this up once we have tests that pass in a real TUN fd. Theconn.go
changes I just copied from Spike's prototype branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Unfortunately, ordering does matter here in general. It might be possible to do it better.
Uh oh!
There was an error while loading.Please reload this page.
func (wworkspace)addAllDNSNames(namesmap[dnsname.FQDN][]netip.Addr,ownerstring)error { | ||
for_,a:=rangew.agents { | ||
// updateDNSNames updates the DNS names for all agents in the workspace. | ||
func (w*Workspace)updateDNSNames()error { |
ethanndicksonNov 25, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Including all the FQDNs as part of an outgoing workspace update was kinda tricky, particularly because of thelen(agents) == 1
alias.
This solution just has this function update the hosts on each agent, and then store all the agents and workspaces as pointers. This lets us build our workspace update as we apply the diff to the state, and then before sending, we fill in all the correct FQDNs, which applies to both the state, and the outgoing update.
func (t*tunnelUpdater)updateDNSNames()map[dnsname.FQDN][]netip.Addr { | ||
names:=make(map[dnsname.FQDN][]netip.Addr) | ||
for_,w:=ranget.workspaces { | ||
err:=w.addAllDNSNames(names,t.ownerUsername) |
ethanndicksonNov 25, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I moved theownerUsername
from an argument when updating a workspace to a private field on theWorkspace
, as it made more sense for future-proofing w.r.t. shared workspaces.
funcUseAsRouter()TunnelOption { | ||
returnfunc(t*Tunnel) { | ||
t.router=NewRouter(t) | ||
} | ||
} | ||
funcUseAsLogger()TunnelOption { | ||
returnfunc(t*Tunnel) { | ||
t.logger=t.logger.AppendSinks(t) | ||
} | ||
} | ||
funcUseAsDNSConfig()TunnelOption { | ||
returnfunc(t*Tunnel) { | ||
t.dnsConfigurator=NewDNSConfigurator(t) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Do we ever not want these things? They should just be the default and we should removeTunnelOption
until the need arises
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Spike suggested earlier:#15612 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I honestly prefer the separate build tag files that do the implementations for each of these on each platform but to each their own
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
469ff7a
to07dc614
Compare07dc614
to359aaeb
Compareba48069
intomainUh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Addresses#14734.
This PR wires up
tunnel.go
to atailnet.Conn
via the new/tailnet
endpoint, with all the necessary controllers such that a VPN connection can be started, stopped and inspected via the CoderVPN protocol.