Egress
An EgressAn outbound SOCKS5 proxy that the caller runs. When a Workspace's network policy references it, TCP connections to the given ranges leave from the caller's network. is a SOCKS5 endpoint that the caller runs. Once a Workspace's network policy references it, TCP connections to the given ranges leave from the caller's network. This page shows how to create, reference, update, and delete an Egress, and when connections go out through it.
Prerequisites
The server must support Egress. Without it, kibo egress, and kibo workspace network commands with Egress flags or --drain-seconds, exit with 14 and send no request. For the capability name, see With the API.
Creating an Egress
The commands below create an Egress with a label, show it, and list the Egresses with that label:
egress_id=$(kibo egress create --address proxy.example.com:1080 --username alice --password-file ./proxy-password --label team=infra -q)
kibo egress get "$egress_id"
kibo egress list -l team=infraCreate and update describe the complete endpoint:
| Flag | Rules |
|---|---|
--address | Required. host:port, where host is an IP address or a host name |
--username and password | Optional. When given, both are required, each 1 to 255 bytes, authenticated per RFC 1929. See Passwords |
--tls, --tls-server-name, --tls-ca-cert-file | Turn on TLS. SOCKS5 negotiation and forwarded traffic are both inside TLS. Giving either of the last two flags also turns on TLS. The verification name defaults to the endpoint's host. The CA is PEM, at most 64 KiB, and replaces the system trust store when given |
--udp | Off by default. When on, a policy that references this Egress can send the queries of a udp Resolver through it, carried by SOCKS5 UDP ASSOCIATE |
--label, --annotation | Given only at creation and modified separately afterwards; see Labels and annotations |
Warning
With TLS on, UDP datagrams are not protected by TLS. They go in plaintext to the relay address the endpoint replies with.
- The endpoint is checked once at create and update. When the IP address falls in a fixed special-purpose range such as private, loopback, multicast, or documentation, or when the host name resolves once on ctrl to a result that includes such an address, the request returns
invalid_argument. This step only catches mistakes early: the node resolves the name again on every dial, removes disallowed addresses, and connects only to the rest. - Each Egress has its own revision. The server assigns it: 1 at creation, incremented when the endpoint settings change. It is independent of the revision of policies that reference the Egress.
Passwords
kibo has no flag that takes the password value directly, so the password stays out of shell history and the process list.
- Read it from standard input with
--password-stdin, or from a file with--password-file. - When you give only
--username,kiboprompts for the password on the terminal without echo. Without a terminal, it exits with2. - One trailing newline at the end of standard input or the file is removed. All other characters are part of the password.
- The password is write-only. No read, list, command output, or error message returns it. The user name is returned as usual, and the details only say whether credentials are configured.
Routing connections through an Egress
A public-internet policy can reference an Egress and list the destination ranges that go out through it. New TCP connections whose destination falls in these ranges are forwarded via Egress, and everything else goes direct as usual. In the diagram below, the ranges contain only 10.0.0.0/8:
The commands below reference the Egress for all IPv4 and IPv6 destinations, add and then remove the range 10.0.0.0/8, and finally remove the reference:
kibo workspace network set "$workspace_id" public-internet --egress "$egress_id" --egress-destination 0.0.0.0/0 --egress-destination ::/0
kibo workspace network add "$workspace_id" --egress-destination 10.0.0.0/8
kibo workspace network remove "$workspace_id" --egress-destination 10.0.0.0/8
kibo workspace network remove "$workspace_id" --egress "$egress_id"| Command | Effect on the Egress |
|---|---|
network set, workspace create | --egress with at least one --egress-destination writes one entry. Without --egress, the policy references no Egress |
network add | When the policy has no Egress yet, --egress with --egress-destination references it. When it has one, --egress-destination adds ranges to it, and --egress can only be the same ID |
network remove | --egress-destination removes ranges, leaving at least one. --egress alone removes the reference, and those ranges go direct again |
When add and remove edit --allow and --deny, they keep the existing Egress entry. When the policy they read already references an Egress, add and remove also require the Egress capability.
- A policy references at most one Egress, with 1 to 256 ranges. More than one entry, empty ranges or more than 256, non-canonical entries, and
DENY_ALLwith an Egress all returninvalid_argument, and the desired policy does not change. - Ranges are written the same way as
allowanddeny. Each applies only to its own address family. - The Egress must exist. When it does not exist or is deleted, the request returns
not_found. - Only nodes that support Egress receive it. When no node that advertises the exit capability is available at creation or start, the request returns
failed_preconditionwithreasonset toCAPABILITY_UNAVAILABLE. The Workspace never runs with a policy that drops the Egress. When you add an Egress to a running Workspace whose node does not support it, the request returns the same error and the desired policy does not change. - Changing only the order of ranges is a content change and increments the revision, but it does not change where any connection goes.
Where connections go
New TCP connections whose destination is inside the ranges go to the forwarding service on the node, which sends a CONNECT to the SOCKS5 endpoint for the destination address the guest originally wanted to reach:
A connection is matched in this order:
- To port 53 of the link DNS address: handled by Link DNS, not forwarded via Egress by destination.
- In
denyand not inallow: refused. Private-network entries apply as well. - New TCP whose destination is inside the ranges: forwarded via Egress, without the refusal of private and special-purpose addresses.
pingwhose destination is inside the ranges: refused immediately with ICMP administratively prohibited.- Everything else: goes direct according to Destination matching.
The ranges can include private and platform ranges. Connections via Egress leave from the caller's network and are not subject to the private-address refusal that applies to direct connections. The diagram below shows that the same address is still refused when sent direct:
When the destination is inside the ranges, each kind of traffic goes as follows:
| Traffic | Where it goes |
|---|---|
| TCP initiated by the guest | Forwarded via Egress |
ping | Refused immediately with ICMP administratively prohibited |
| Other UDP initiated by the guest | Same as direct: PUBLIC_INTERNET does not allow it |
| Queries to the link DNS address | Not via Egress. Forwarded queries go out through this Egress only when a Resolver's path names it; see DNS and Resolvers |
A failed exit does not fall back to direct. When the endpoint cannot be reached, TLS verification fails, or SOCKS5 negotiation or authentication fails, the guest's connection is reset. For the causes, see Egress failures.
Changing where connections go
Changes that alter where connections go (from direct to via Egress, the reverse, or replacing the ranges) do not cut off existing connections immediately:
- New connections are established under the new policy immediately. Old connections keep transferring on their original path and close when the grace period ends. During this time,
draining_revisionis the old policy revision. - The grace period is
--drain-secondsof this change, from 0 to 3600, default 600. 0 means close immediately at the switch. - Another change within the grace period does not extend an earlier deadline.
- Connections that the new mode,
allow, ordenyno longer allow are terminated immediately, without waiting for the grace period.
| Change | Established connections |
|---|---|
Ranges changed from 10.0.0.0/8 to 0.0.0.0/0 | Internet connections that were going direct keep transferring and close when the grace period ends. New connections go via Egress |
| Egress reference removed | Connections via Egress to 10.0.0.5 keep transferring and close when the grace period ends. New connections go direct and are refused |
10.0.0.5 added to deny in the same change | Terminated immediately |
| Egress deleted after the reference is removed | Connections still within the grace period close immediately |
Updating an Egress
An update returns once ctrl saves it, without waiting for Workspaces. Running Workspaces that reference the Egress then switch new connections to the new revision, and existing connections close according to this update's grace period. The diagram below shows the switch:
| Time | What happens | How you see it |
|---|---|---|
Run kibo egress update (UpdateEgress) | The change is saved by ctrl and the revision goes from 3 to 4, then the call returns | The Egress revision is 4 |
| Before the switch | The node gets the new configuration; new connections still use revision 3 | This Egress's applied_revision in the Workspace is 3 |
| Switch, usually within 30 seconds | New connections use revision 4; revision 3 connections keep transferring | applied_revision is 4, draining_revision is 3 |
| Grace period ends | Revision 3 connections close | draining_revision is 0 |
The command below updates the Egress and closes connections on the old revision 60 seconds after the switch:
kibo egress update "$egress_id" --address proxy.example.com:1080 --username alice --password-file ./proxy-password --drain-seconds 60- An update replaces the whole Egress. Flags you leave out of
kibo egress updateare empty. The password cannot be read back, so give it again on every update. - Concurrent updates are refused. Without
--expected-revision,kiboreads the current revision first and then submits, and exits with13if someone else changed the Egress in the meantime. When a script replays, pass--command-idand--expected-revisiontogether. - An update with the same content succeeds, and the revision does not change.
- The grace period is a parameter of this update.
--drain-secondsis from 0 to 3600, default 600. 0 means close immediately at the switch. It is not saved with the Egress. - When the node cannot get the new configuration for a while, it keeps the original revision. The update is retried by ctrl, and the Workspace state does not change.
- UDP cannot be turned off while a
udpResolver still goes out through the Egress. Such an update returnsfailed_precondition(CONFLICT),kiboexits with13, and the content does not change. - Compare the two revisions to check whether the update is in effect. When this Egress's applied revision in the Workspace status equals the Egress revision, new connections already use the new configuration; see Confirming the policy is in effect.
Deleting an Egress
A referenced Egress cannot be deleted, so the commands below remove the reference first and then delete the Egress:
kibo workspace network remove "$workspace_id" --egress "$egress_id"
kibo egress delete "$egress_id"- While the policy of any Workspace that is not deleted references the Egress, deletion returns
failed_precondition(CONFLICT) andkiboexits with13. - After deletion, connections still using the Egress within their grace period close immediately.
- A deleted Egress returns
not_foundfor every read and reference.
With the API
Egresses are managed with EgressService, and every write operation carries a command ID; see Command IDs. The flags in Creating an Egress map to these fields:
| kibo flag | API field |
|---|---|
--address | socks5.address |
--username and password | socks5.username, socks5.password |
--tls, --tls-server-name, --tls-ca-cert-file | socks5.tls |
--udp | udp_enabled |
--label, --annotation | labels, annotations |
spec.socks5is the endpoint protocol. Only SOCKS5 exists for now. Create and update without a protocol returninvalid_argument.revisionis assigned by the server: 1 at creation, incremented whenspecchanges.- An update must carry an expected revision. If that does not match the current revision, the update returns
aborted(reasonset toCONFLICT) and the content does not change. - In the network policy, the Egress is
egresses. Each entry has anegress_idand itsdestinations. - The grace period of a policy change or an Egress update is
drain_seconds.
A server that supports Egress advertises the capability workspace.network_policy.egress.socks5. In the future, each exit protocol will have its own capability name, and callers use it to tell which protocols a deployment supports.
Warning
Older servers silently drop egresses. Confirm that the capability name exists before writing it.
Next steps
- DNS and Resolvers: send DNS queries through the Egress with a Resolver.
- Network troubleshooting: confirm an update is in effect, and find out why connections via Egress are reset.
- Network policy: destination rules and when a policy change takes effect.
Network policy
The mode and destination rules of a network policy decide which addresses a Workspace can reach directly. This page shows how to change them with kibo, how a destination address is matched, and when a change takes effect.
DNS and Resolvers
This page explains where the guest's DNS queries go, and how to hand them to an upstream the caller chooses with a Resolver.