# Use a SOCKS5 Proxy to Access the Kubernetes API

LLMS index: [llms.txt](/llms.txt)

---

<!-- overview -->








  <div class="feature-state-notice feature-stable">
      <span class="feature-state-name">FEATURE STATE:</span>
      <code>Kubernetes v1.24 [stable]</code>
    </div>
  



This page shows how to use a SOCKS5 proxy to access the API of a remote Kubernetes cluster.
This is useful when the cluster you want to access does not expose its API directly on the public internet.

## Before you begin

<p>You need to have a Kubernetes cluster, and the kubectl command-line tool must
be configured to communicate with your cluster. It is recommended to run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you do not already have a
cluster, you can create one by using
<a href="https://minikube.sigs.k8s.io/docs/tutorials/multi_node/">minikube</a>
or you can use one of these Kubernetes playgrounds:</p>
<ul>
<li><a href="https://labs.iximiuz.com/playgrounds?category=kubernetes&filter=all">iximiuz Labs</a></li>
<li><a href="https://killercoda.com/playgrounds/scenario/kubernetes">Killercoda</a></li>
<li><a href="https://kodekloud.com/public-playgrounds">KodeKloud</a></li>
</ul>
 
 
 Your Kubernetes server must be at or later than version v1.24.
  <p>To check the version, enter  <code>kubectl version</code>.</p>


You need SSH client software (the `ssh` tool), and an SSH service running on the remote server.
You must be able to log in to the SSH service on the remote server.

<!-- steps -->

## Task context


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>This example tunnels traffic using SSH, with the SSH client and server acting as a SOCKS proxy.
You can instead use any other kind of <a href="https://en.wikipedia.org/wiki/SOCKS#SOCKS5">SOCKS5</a> proxies.</div>


Figure 1 represents what you're going to achieve in this task.

* You have a client computer, referred to as local in the steps ahead, from where you're going to create requests to talk to the Kubernetes API.
* The Kubernetes server/API is hosted on a remote server.
* You will use SSH client and server software to create a secure SOCKS5 tunnel between the local and
  the remote server. The HTTPS traffic between the client and the Kubernetes API will flow over the SOCKS5
  tunnel, which is itself tunnelled over SSH.


<figure>
<div class="mermaid">
    
graph LR;

  subgraph local[Local client machine]
  client([client])-. local <br> traffic .->  local_ssh[Local SSH <br> SOCKS5 proxy];
  end
  local_ssh[SSH <br>SOCKS5 <br> proxy]-- SSH Tunnel -->sshd
  
  subgraph remote[Remote server]
  sshd[SSH <br> server]-- local traffic -->service1;
  end
  client([client])-. proxied HTTPs traffic <br> going through the proxy .->service1[Kubernetes API];

  classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
  classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff;
  classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
  class ingress,service1,service2,pod1,pod2,pod3,pod4 k8s;
  class client plain;
  class cluster cluster;

</div>
</figure>

<noscript>
  <div class="alert alert-secondary callout" role="note">
    <em class="javascript-required">JavaScript must be <a href="https://www.enable-javascript.com/">enabled</a> to view this content</em>
  </div>
</noscript>

Figure 1. SOCKS5 tutorial components

## Using ssh to create a SOCKS5 proxy

The following command starts a SOCKS5 proxy between your client machine and the remote SOCKS server:

```shell
# The SSH tunnel continues running in the foreground after you run this
ssh -D 1080 -q -N username@kubernetes-remote-server.example
```

The SOCKS5 proxy lets you connect to your cluster's API server based on the following configuration: 
* `-D 1080`: opens a SOCKS proxy on local port :1080.
* `-q`: quiet mode. Causes most warning and diagnostic messages to be suppressed.
* `-N`: Do not execute a remote command. Useful for just forwarding ports.
* `username@kubernetes-remote-server.example`: the remote SSH server behind which the Kubernetes cluster 
  is running (eg: a bastion host).

## Client configuration

To access the Kubernetes API server through the proxy you must instruct `kubectl` to send queries through
the `SOCKS` proxy we created earlier. Do this by either setting the appropriate environment variable, 
or via the `proxy-url` attribute in the kubeconfig file. Using an environment variable: 

```shell
export HTTPS_PROXY=socks5://localhost:1080
```

To always use this setting on a specific `kubectl` context, specify the `proxy-url` attribute in the relevant 
`cluster` entry within the `~/.kube/config` file. For example:

```yaml
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LRMEMMW2 # shortened for readability 
    server: https://<API_SERVER_IP_ADDRESS>:6443  # the "Kubernetes API" server, in other words the IP address of kubernetes-remote-server.example
    proxy-url: socks5://localhost:1080   # the "SSH SOCKS5 proxy" in the diagram above
  name: default
contexts:
- context:
    cluster: default
    user: default
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
  user:
    client-certificate-data: LS0tLS1CR== # shortened for readability
    client-key-data: LS0tLS1CRUdJT=      # shortened for readability
```

Once you have created the tunnel via the ssh command mentioned earlier, and defined either the environment variable or 
the `proxy-url` attribute, you can interact with your cluster through that proxy. For example:

```shell
kubectl get pods
```

```console
NAMESPACE     NAME                                     READY   STATUS      RESTARTS   AGE
kube-system   coredns-85cb69466-klwq8                  1/1     Running     0          5m46s
```


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4><ul>
<li>Before <code>kubectl</code> 1.24, most <code>kubectl</code> commands worked when using a socks proxy, except <code>kubectl exec</code>.</li>
<li><code>kubectl</code> supports both <code>HTTPS_PROXY</code> and <code>https_proxy</code> environment variables. These are used by other
programs that support SOCKS, such as <code>curl</code>. Therefore in some cases it
will be better to define the environment variable on the command line:
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="nv">HTTPS_PROXY</span><span class="o">=</span>socks5://localhost:1080 kubectl get pods
</span></span></code></pre></div></li>
<li>When using <code>proxy-url</code>, the proxy is used only for the relevant <code>kubectl</code> context,
whereas the environment variable will affect all contexts.</li>
<li>The k8s API server hostname can be further protected from DNS leakage by using the <code>socks5h</code> protocol name
instead of the more commonly known <code>socks5</code> protocol shown above. In this case, <code>kubectl</code> will ask the proxy server
(such as an ssh bastion) to resolve the k8s API server domain name, instead of resolving it on the system running
<code>kubectl</code>. Note also that with <code>socks5h</code>, a k8s API server URL like <code>https://localhost:6443/api</code> does not refer
to your local client computer. Instead, it refers to <code>localhost</code> as known on the proxy server (eg the ssh bastion).</li>
</ul>
</div>



## Clean up

Stop the ssh port-forwarding process by pressing `CTRL+C` on the terminal where it is running.

Type `unset https_proxy` in a terminal to stop forwarding http traffic through the proxy.

## Further reading

* [OpenSSH remote login client](https://man.openbsd.org/ssh)
