SOCKS5

Setting the Service mode to SOCKS5 enables it to operate in application-layer aware SOCKS5 proxy mode. This mode enables your Users to reach upstream destinations through a standard SOCKS5 proxy while the Service enforces identity-aware access control on a per-connection basis. This mode also provides you with clear application-layer aware visibility where the requested destinations of your SOCKS5 connections are logged and audited in real-time.

note

Read more about access to SOCKS5 from a User perspective here.

Secretless Access

Secretless access enables you to provide secretless access for authorized Users to SOCKS5-based Service by automatically injecting passwords to authenticate to the upstream SOCKS5 server, and force the User to connect to the upstream as a specific user. The password value is stored in a Secret (read more here) instead of being set in plaintext in the Service configuration.

First, you need to create the Secret as follows:

octeliumctl create secret socks5-password # OR via a --value flag octeliumctl create secret --value <PASSWORD> socks5-password # OR via a --file flag octeliumctl create secret --file /PATH/TO/PASSWORD socks5-password

Now, you define your Service as follows:

kind: Service metadata: name: socks5 spec: mode: SOCKS5 port: 1080 config: upstream: url: tcp://address-to-host socks5: auth: usernamePassword: username: usr1 password: fromSecret: socks5-password

You can also explicitly instruct Vigil to use no authentication when connecting to the upstream server via the noAuth field as follows:

kind: Service metadata: name: socks5 spec: mode: SOCKS5 port: 1080 config: upstream: url: tcp://address-to-host socks5: auth: noAuth: true
note

For internal/private upstreams behind NAT, you need to remotely serve them via a connected octelium client or container as discussed here.

Embedded Mode

By default, the Service proxies SOCKS5 connections to the upstream set in the upstream field. You can, however, enable the "embedded" mode where the SOCKS5 proxy is served from within a connected octelium client rather than proxied to a separate upstream proxy server. In this mode, the connected client itself acts as the SOCKS5 egress point, which means the connections to the final destinations originate from the host running the octelium client. You can enable it via the isEmbeddedMode field as follows:

kind: Service metadata: name: socks5 spec: mode: SOCKS5 port: 1080 config: socks5: isEmbeddedMode: true

A User announces their intent to serve embedded SOCKS5 when connecting to the Cluster via the --esocks5 flag in the octelium connect command (read more here). Authorized Users then reach the embedded SOCKS5 proxy of a certain Session by using the Session's name as the SOCKS5 username. You can read more about accessing embedded SOCKS5 from a User perspective here.

note

The Cluster comes with a built-in socks5.octelium Service that operates in embedded mode, so you do not need to create your own embedded SOCKS5 Service in order to reach the embedded SOCKS5 proxies served by connected Sessions.

Access Control

You can control access based on the SOCKS5 request information. Such information is stored in ctx.request.socks5 where it contains the requested destination host, port and address type of the connection. Here is a detailed example of an inline Policy that controls access based on SOCKS5-specific information:

kind: Service metadata: name: svc1 spec: mode: SOCKS5 port: 1080 config: upstream: url: tcp://address-to-host # rest of the config authorization: inlinePolicies: - spec: rules: - effect: ALLOW condition: any: of: - match: ctx.request.socks5.connect.host.endsWith(".example.com") - match: ctx.request.socks5.connect.port == 443

The address type of the requested destination is also available in ctx.request.socks5.connect.addressType which can be one of IPV4, DOMAIN or IPV6. Here is an example that only allows connections to domain-based destinations:

kind: Service metadata: name: svc1 spec: mode: SOCKS5 port: 1080 config: upstream: url: tcp://address-to-host authorization: inlinePolicies: - spec: rules: - effect: ALLOW condition: match: ctx.request.socks5.connect.addressType == "DOMAIN"

Dynamic Configuration

You can use dynamic configuration in order to, for example, route to different upstreams or use different proxy credentials depending on the request's context (read more about dynamic configuration here). Here is an example where Users belonging to the ops Group are proxied to one upstream while the rest are proxied to another:

kind: Service metadata: name: example-svc spec: mode: SOCKS5 port: 1080 dynamicConfig: configs: - name: ops upstream: url: tcp://host-1:1080 socks5: auth: usernamePassword: username: ops password: fromSecret: ops-password - name: dev upstream: url: tcp://host-2:1080 socks5: auth: noAuth: true rules: - condition: match: '"ops" in ctx.user.spec.groups' configName: ops - condition: matchAny: true configName: dev

Visibility

The Service emits access logs in real time to the audit collector. Each log provides SOCKS5 application-layer aware information about the connection such as the requested destination host, port and address type. Here is an example:

{ "apiVersion": "core/v1", "kind": "AccessLog", "metadata": { "id": "k3r8-2m1p-9wzt5xq7brhdmnkpttyabqsx-ai0l-7c2v", "createdAt": "2025-09-10T22:41:03.184524267Z", "actorRef": { "apiVersion": "core/v1", "kind": "Session", "uid": "b1bc6aaa-df51-456d-aa37-b77377ea26f0", "name": "usr1-3pt93j", "resourceVersion": "019935bf-8271-704d-b079-9af18e29037a" }, "targetRef": { "apiVersion": "core/v1", "kind": "Service", "uid": "8ca3d118-a507-405f-8592-12a5fe1e16cb", "name": "socks5.default", "resourceVersion": "019934ca-9270-7480-8d96-230a538cb6a6" } }, "entry": { "common": { "startedAt": "2025-09-10T22:41:03.182784369Z", "endedAt": "2025-09-10T22:41:03.184526057Z", "status": "ALLOWED", "mode": "SOCKS5", "sessionRef": { "apiVersion": "core/v1", "kind": "Session", "uid": "b1bc6aaa-df51-456d-aa37-b77377ea26f0", "name": "usr1-3pt93j", "resourceVersion": "019935bf-8271-704d-b079-9af18e29037a" }, "userRef": { "apiVersion": "core/v1", "kind": "User", "uid": "d72a39da-6f1c-43f7-ad75-dbaf76111b10", "name": "usr1", "resourceVersion": "019934c7-3d99-7864-8ccf-abe9eadfe023" }, "serviceRef": { "apiVersion": "core/v1", "kind": "Service", "uid": "8ca3d118-a507-405f-8592-12a5fe1e16cb", "name": "socks5.default", "resourceVersion": "019934ca-9270-7480-8d96-230a538cb6a6" }, "namespaceRef": { "apiVersion": "core/v1", "kind": "Namespace", "uid": "659a016d-aa9b-45c5-aae7-4212e7d4da3d", "name": "default", "resourceVersion": "019934c7-6d7e-76d0-89c7-2966e41f2e5b" }, "regionRef": { "apiVersion": "core/v1", "kind": "Region", "uid": "85477de2-67d3-48ed-bda7-6c914489badf", "name": "default" } }, "info": { "socks5": { "type": "CONNECT", "host": "api.example.com", "port": 443, "addressType": "DOMAIN" } } } }

As you can see in the above example, the type of this SOCKS5 access Log is a CONNECT. The SOCKS5 mode has currently 2 Log types: CONNECT and SESSION_END, where the SESSION_END type additionally includes the number of received and sent bytes as well as the resolved upstream host and port. You can read more in the API reference.