# TCP

> Octelium documentation. Canonical page: <https://octelium.com/docs/octelium/latest/management/core/service/tcp>.

The `TCP` mode can be used for generic TCP-based applications. Here is an example:

```yaml
kind: Service
metadata:
  name: nats
spec:
  port: 8080
  mode: TCP
  config:
    upstream:
      url: tcp://nats-server:8080
```

> **Note:**
>
> Octelium supports a various of TCP-based application-layer protocols such as HTTP, SSH, PostgreSQL and MySQL. Using such modes instead of `TCP` provides you with features such as L7 aware access control, secretless access to upstreams, L7 aware dynamic configuration and L7 aware visibility. Read more [here](https://octelium.com/docs/octelium/latest/management/core/service/overview.md#mode).

## Access Control

Compared to application-layer aware modes such as `HTTP` and `KUBERNETES` where access control happens on every application-layer request where application-layer info are fed to the request context, access control in `TCP` mode obviously happens only at the beginning of the TCP connection and there is no specific L7 information can be extracted. Here is an example:

```yaml
kind: Service
metadata:
  name: example-svc
spec:
  port: 8080
  mode: TCP
  config:
    upstream:
      url: tcp://nats-server:8080
  authorization:
    inlinePolicies:
      - spec:
          rules:
            - effect: ALLOW
              condition:
                match: '"group-1" in ctx.user.spec.groups'
```

## Secretless Access

You can provide secretless access to your *Users* (read more about secretless access [here](https://octelium.com/docs/octelium/latest/management/core/service/secretless.md)) to any TCP-based application layer protocol that is protected by mutual TLS (mTLS). Read more in detail [here](https://octelium.com/docs/octelium/latest/management/core/service/secretless.md#mutual-tls).

## Dynamic Configuration

You can use dynamic configuration in order to, for example, route to different upstreams or use different mTLS certificates (read more about secretless access via mTLS [here](https://octelium.com/docs/octelium/latest/management/core/service/secretless.md#mutual-tls)) depending on the request's context (read more about dynamic configuration [here](https://octelium.com/docs/octelium/latest/management/core/service/dynamic-config.md)). Here is an example:

```yaml
kind: Service
metadata:
  name: ssh1
spec:
  mode: TCP
  config:
    upstream:
      url: tcp://host-0:9000
  dynamicConfig:
    configs:
      - name: host-1
        upstream:
          url: tcp://host-1:9001
      - name: host-2
        upstream:
          url: tcp://host-2:9002
    rules:
      - condition:
          match: '"ops" in ctx.user.spec.groups'
        configName: host-1
      - condition:
          match: '"dev" in ctx.user.spec.groups'
        configName: host-2
```

## TLS

By default, the *Service* listens over plaintext TCP regardless of whether the upstream is listening over TCP or TLS. You can force the *Service* to listen over TLS, however, via the `isTLS` flag as follows:

```yaml
kind: Service
metadata:
  name: my-nats
spec:
  mode: TCP
  port: 9000
  # !mark
  isTLS: true
  config:
    upstream:
      url: tcp://nats-server:8080
```

If the upstream is listening over TLS and using a certificate that is signed by private CA, you will have to manually add that root CA in a list of `trustedCAs`. Here is an example:

```yaml
kind: Service
metadata:
  name: my-api
spec:
  mode: TCP
  config:
    upstream:
      url: tls://my-upstream:6443
    # !mark(1:6)
    tls:
      trustedCAs:
      - |
        -----BEGIN CERTIFICATE-----
        CA
        -----END CERTIFICATE-----
```

You can also skip verifying the upstream's certificate altogether via the `insecureSkipVerify` which is typically recommended only for troubleshooting/testing use cases. Here is an example:

```yaml
kind: Service
metadata:
  name: my-api
spec:
  mode: TCP
  config:
    upstream:
      url: tls://my-upstream:6443
    # !mark(1:2)
    tls:
      insecureSkipVerify: true
```

If the upstream requires mutual TLS (mTLS), you will have to include your client certificate private key as a *Secret* (read more [here](https://octelium.com/docs/octelium/latest/management/core/secret.md#tls-certificate)), and then reference it as follows:

```yaml
kind: Service
metadata:
  name: my-api
spec:
  mode: TCP
  config:
    upstream:
      url: tls://my-upstream:6443
    tls:
      trustedCAs:
      - |
        -----BEGIN CERTIFICATE-----
        CA
        -----END CERTIFICATE-----
      # !mark(1:2)
      clientCertificate:
        fromSecret: client-private-key
```

## Visibility

The *Service* emits access logs in real time to the audit collector. Here is an example of a `TCP` *Log*:

```json
{
  "apiVersion": "core/v1",
  "entry": {
    "common": {
      "connectionID": "vldv-kx0n-jz20ix83wijy7p605o61puha-zpq6-2z7k",
      "endedAt": "2025-03-21T22:28:53.184219118Z",
      "isAuthenticated": true,
      "isAuthorized": true,
      "namespaceRef": {
        "apiVersion": "core/v1",
        "kind": "Namespace",
        "name": "default",
        "resourceVersion": "0195b81d-43ec-7ba7-81f7-9b77202b3612",
        "uid": "bff0768e-eec8-4044-a972-9f7af81b79d8"
      },
      "regionRef": {
        "apiVersion": "core/v1",
        "kind": "Region",
        "name": "default",
        "uid": "6e233d12-2fd6-4670-a82d-8c712e1f7374"
      },
      "serviceRef": {
        "apiVersion": "core/v1",
        "kind": "Service",
        "name": "pg2.default",
        "resourceVersion": "0195bad1-6f83-7740-8db5-ca41ad514d3f",
        "uid": "92e79dbb-5f69-419d-b41d-ca26cb892a4a"
      },
      "sessionRef": {
        "apiVersion": "core/v1",
        "kind": "Session",
        "name": "usr1-3pt93j",
        "resourceVersion": "0195bad0-8169-7c53-a2a4-eef7b5b23880",
        "uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"
      },
      "startedAt": "2025-03-21T22:28:07.494538911Z",
      "userRef": {
        "apiVersion": "core/v1",
        "kind": "User",
        "name": "usr1",
        "resourceVersion": "0195b821-228d-79b2-92f3-4bb458944f97",
        "uid": "e0f251b2-6952-4a46-a771-2712a45c47f5"
      }
    },
    "info": {
      "tcp": {
        "receivedBytes": "30253",
        "sentBytes": "2876",
        "type": "END"
      }
    }
  },
  "kind": "AccessLog",
  "metadata": {
    "actorRef": {
      "apiVersion": "core/v1",
      "kind": "Session",
      "name": "usr1-3pt93j",
      "resourceVersion": "0195bad0-8169-7c53-a2a4-eef7b5b23880",
      "uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"
    },
    "createdAt": "2025-03-21T22:28:53.184211348Z",
    "id": "q41j-e6m6-7wvk7mr90dy36kbbaxtpfmeh-ail9-8z34",
    "targetRef": {
      "apiVersion": "core/v1",
      "kind": "Service",
      "name": "pg2.default",
      "resourceVersion": "0195bad1-6f83-7740-8db5-ca41ad514d3f",
      "uid": "92e79dbb-5f69-419d-b41d-ca26cb892a4a"
    }
  }
}
```
