# Access an IP address behind a subnet router

Last validated Jun 5, 2026

You can make an IP address that is behind a [subnet router][kb-subnet-routers] accessible to your Kubernetes cluster workloads using an egress `ProxyGroup`. This is useful for accessing resources that are not directly on your tailnet but are reachable through a subnet router, such as databases or internal services on a private network.

Your cluster workloads access the target using a Kubernetes `Service` name, like any other in-cluster Kubernetes `Service`.

![A diagram showing ProxyGroup egress architecture for accessing an IP address behind a subnet router.](kubernetes-operator/_diagrams/proxygroup-egress-architecture.svg)

## Prerequisites

Before you begin, make sure you have the following:

* [Install][kb-k8s-install] the Tailscale Kubernetes Operator.
* A [subnet router][kb-subnet-routers] advertising the route that contains the target IP address.

## Create a ProxyClass to accept routes

To reach the target IP address, the egress proxy must accept advertised subnet routes. Create a `ProxyClass` with `acceptRoutes` enabled:

```yaml
apiVersion: tailscale.com/v1alpha1
kind: ProxyClass
metadata:
  name: accept-routes
spec:
  tailscale:
    acceptRoutes: true
```

## Create an egress ProxyGroup

Create a `ProxyGroup` with `spec.type` set to `egress` and `spec.proxyClass` set to the `ProxyClass` created above:

```yaml
apiVersion: tailscale.com/v1alpha1
kind: ProxyGroup
metadata:
  name: egress-proxies
spec:
  type: egress
  replicas: 2
  proxyClass: accept-routes
```

Refer to [High availability for the Tailscale Kubernetes Operator][kb-ha] for production configuration options.

## Create an egress Kubernetes Service

Create a Kubernetes `ExternalName` `Service` that references the `ProxyGroup` and the target IP address:

```yaml
apiVersion: v1
kind: Service
metadata:
  name: my-subnet-target
  annotations:
    tailscale.com/tailnet-ip: "<ip-behind-subnet-router>"
    tailscale.com/proxy-group: "egress-proxies"
spec:
  type: ExternalName
  externalName: placeholder
  ports:
    - port: 80
      protocol: TCP
      name: http
```

The `externalName` field is overwritten by the Operator. Set `spec.ports` to match the ports exposed by the target.

> **Note:**
>
> The Kubernetes `ExternalName` `Service` must explicitly list all ports you want to access in `spec.ports`. Only `port`, `protocol`, and `name` are used. Other port fields have no effect.

## Verify access

Wait for the Kubernetes `Service` to become ready:

```shell
kubectl wait svc my-subnet-target --for=condition=TailscaleEgressSvcReady=true --timeout=5m
```

Access the target from your workloads using the Kubernetes DNS name:

```shell
curl http://my-subnet-target.default.svc.cluster.local
```

Traffic is round-robin load balanced across the `ProxyGroup` replicas. Any number of egress `Service` resources can reference a single `ProxyGroup`.

## Limitations

The following limitations apply to IP-based egress access through subnet routers:

* Only single IP addresses are supported. IP ranges are not supported.
* 4via6 addresses are not supported.

Refer to [IPv6 support][kb-ipv6] for more information.

## Further exploration

* [Access a tailnet device][kb-access-device] from your Kubernetes cluster using an egress proxy.
* Learn more about [egress][kb-egress] in the Tailscale Kubernetes Operator.
* Configure [high availability][kb-ha] for production deployments.
* Learn more about [subnet routers][kb-subnet-routers].

[kb-access-device]: /docs/kubernetes-operator/egress/access-tailnet-service

[kb-egress]: /docs/kubernetes-operator/egress

[kb-ha]: /docs/kubernetes-operator/manage-and-configure/high-availability

[kb-ipv6]: /docs/kubernetes-operator/reference/ipv6

[kb-k8s-install]: /docs/kubernetes-operator/install-operator

[kb-subnet-routers]: /docs/features/subnet-routers
