mirror of
https://github.com/davegallant/davegallant.github.io.git
synced 2025-08-05 08:13:40 +00:00
224 lines
11 KiB
HTML
224 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html><head>
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Using AKS and SOCKS to connect to a Private Azure DB - davegallant</title><link rel="icon" type="image/png" href=https://davegallant.ca/favicon.ico /><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="description" content="" />
|
|
<meta property="og:image" content=""/>
|
|
<meta property="og:title" content="Using AKS and SOCKS to connect to a Private Azure DB" />
|
|
<meta property="og:description" content="" />
|
|
<meta property="og:type" content="article" />
|
|
<meta property="og:url" content="/blog/2023/05/22/using-aks-and-socks-to-connect-to-a-private-azure-db/" /><meta property="article:section" content="post" />
|
|
<meta property="article:published_time" content="2023-05-22T16:31:29-04:00" />
|
|
<meta property="article:modified_time" content="2023-05-22T16:31:29-04:00" />
|
|
|
|
<meta name="twitter:card" content="summary"/>
|
|
<meta name="twitter:title" content="Using AKS and SOCKS to connect to a Private Azure DB"/>
|
|
<meta name="twitter:description" content=""/>
|
|
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
|
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@1,500&display=swap" rel="stylesheet">
|
|
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans&display=swap" rel="stylesheet">
|
|
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
|
|
|
|
|
|
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.0e5aa3b634b92d61bafebfd908290cc7a034e4d50e6a0c59ce50044560179c4e.css" />
|
|
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.b11f422ffce8151207bad84653d44cb512043f9efe93a0a049f836b9cc32b34a.css" disabled />
|
|
|
|
|
|
|
|
|
|
<script type="text/javascript"
|
|
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
|
|
</script>
|
|
|
|
|
|
<script type="text/x-mathjax-config">
|
|
MathJax.Hub.Config({
|
|
tex2jax: {
|
|
inlineMath: [['$','$'], ['\\(','\\)']],
|
|
displayMath: [['$$','$$'], ['\[','\]']],
|
|
processEscapes: true,
|
|
processEnvironments: true,
|
|
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
|
|
TeX: { equationNumbers: { autoNumber: "AMS" },
|
|
extensions: ["AMSmath.js", "AMSsymbols.js"] }
|
|
}
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css">
|
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.js"></script>
|
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/contrib/auto-render.min.js" onload="renderMathInElement(document.body);"></script>
|
|
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
renderMathInElement(document.body, {
|
|
delimiters: [
|
|
{left: "$$", right: "$$", display: true},
|
|
{left: "$", right: "$", display: false}
|
|
]
|
|
});
|
|
});
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" type="text/css" href="/css/custom.2e59ff60a2d9c7e42e3c1af2aff0ba627da46f910a234867e98d178eb05c87dc.css">
|
|
|
|
</head>
|
|
<body>
|
|
<div class="content"><header>
|
|
<div class="main">
|
|
<a href="/">davegallant</a>
|
|
</div>
|
|
<nav>
|
|
|
|
<a href="/">Home</a>
|
|
|
|
<a href="/post">All posts</a>
|
|
|
|
<a href="/index.xml">RSS</a>
|
|
|
|
<a href="/tags">Tags</a>
|
|
|
|
<a href="/about">About</a>
|
|
|
|
| <span id="dark-mode-toggle" onclick="toggleTheme()"></span>
|
|
<script src="/js/themetoggle.js"></script>
|
|
|
|
</nav>
|
|
</header>
|
|
|
|
<main>
|
|
<article>
|
|
<div class="title">
|
|
<h1 class="title">Using AKS and SOCKS to connect to a Private Azure DB</h1>
|
|
<div class="meta">Posted on May 22, 2023</div>
|
|
</div>
|
|
|
|
|
|
<section class="body"><h2 id="the-problem">The Problem<a href="#the-problem" class="hanchor" ariaLabel="Anchor">#</a></h2>
|
|
<p>I ran into a roadblock recently where I wanted to be able to conveniently connect to a managed postgres database within Azure that was not running on public subnets. And by conveniently, I mean that I’d rather not have to spin up an ephemeral virtual machine running in the same network and proxy the connection, and I’d like to use a local client (preferably with a GUI). After several web searches, it became evident that Azure does not readily provide much tooling to support this.</p>
|
|
<h2 id="go-public">Go Public?<a href="#go-public" class="hanchor" ariaLabel="Anchor">#</a></h2>
|
|
<p>Should the database be migrated to public subnets? Ideally not, since it is good practice to host internal infrastructure in restricted subnets.</p>
|
|
<h2 id="how-do-others-handle-this">How do others handle this?<a href="#how-do-others-handle-this" class="hanchor" ariaLabel="Anchor">#</a></h2>
|
|
<p>With GCP, connecting to a private db instance from any machine can be achieved with <a href="https://github.com/GoogleCloudPlatform/cloud-sql-proxy">cloud-sql-proxy</a>. This works by proxying requests from your machine to the SQL database instance in the cloud, while the authentication is handled by GCP’s IAM.</p>
|
|
<p>So what about Azure? Is there any solution that is as elegant as cloud-sql-proxy?</p>
|
|
<h2 id="a-bastion">A Bastion<a href="#a-bastion" class="hanchor" ariaLabel="Anchor">#</a></h2>
|
|
<p>Similar to what <a href="https://aws.amazon.com/blogs/database/securely-connect-to-an-amazon-rds-or-amazon-ec2-database-instance-remotely-with-your-preferred-gui/">AWS has recommended</a>, perhaps a bastion is the way forward?</p>
|
|
<p>Azure has a fully-managed service called <a href="https://azure.microsoft.com/en-ca/products/azure-bastion">Azure Bastion</a> that provides secure access to virtual machines that do not have public IPs. This looks interesting, but unfortunately it <a href="https://azure.microsoft.com/en-ca/pricing/details/azure-bastion/#pricing">costs money</a> and requires an additional virtual machine.</p>
|
|
<p>Because this adds cost (and complexity), it does not seem like a desirable option in its current state. If it provided a more seamless connection to the database, it would be more appealing.</p>
|
|
<h2 id="socks">SOCKS<a href="#socks" class="hanchor" ariaLabel="Anchor">#</a></h2>
|
|
<p><a href="https://en.wikipedia.org/wiki/SOCKS">SOCKS</a> is a protocol that enables a way to proxy connections by exchanging network packets between the client and the server. There are many implementations and many readily available container images that can run a SOCKS server.</p>
|
|
<p>It’s possible to use this sort of proxy to connect to a private DB, but is it any simpler than using a virtual machine as a jumphost? It wasn’t until I stumbled upon <a href="https://github.com/yokawasa/kubectl-plugin-socks5-proxy">kubectl-plugin-socks5-proxy</a> that I was convinced that using SOCKS could be made simple.</p>
|
|
<p>So how does it work? By installing the kubectl plugin and then running <code>kubectl socks5-proxy</code>, a SOCKS proxy server is spun up in a pod and then opens up port-forwarding session using kubectl.</p>
|
|
<p>As you can see below, this k8s plugin is wrapped up nicely:</p>
|
|
<pre><code class="language-console">$ kubectl socks5-proxy
|
|
using: namespace=default
|
|
using: port=1080
|
|
using: name=davegallant-proxy
|
|
using: image=serjs/go-socks5-proxy
|
|
Creating SOCKS5 Proxy (Pod)...
|
|
pod/davegallant-proxy created
|
|
</code></pre>
|
|
<p>With the above proxy connection open, it is possible to access both the DNS and private IPs accessible within the k8s cluster. In this case, I am able to access the private database, since there is network connectivity between the k8s cluster and the database.</p>
|
|
<h2 id="caveats-and-conclusion">Caveats and Conclusion<a href="#caveats-and-conclusion" class="hanchor" ariaLabel="Anchor">#</a></h2>
|
|
<p>The above outlined solution makes some assumptions:</p>
|
|
<ul>
|
|
<li>there is a k8s cluster</li>
|
|
<li>the k8s cluster has network connectivity to the desired private database</li>
|
|
</ul>
|
|
<p>If these stars align, than this solution might work as a stopgap for accessing a private Azure DB (and I’m assuming this could work similarly on AWS).</p>
|
|
<p>It would be nice if Azure provided tooling similar to cloud-sql-proxy, so that using private databases would be more of a convenient experience.</p>
|
|
<p>One other thing to note is that some clients (such as <a href="https://dbeaver.io/">dbeaver</a>) <a href="https://github.com/dbeaver/dbeaver/issues/872">do not provide DNS resolution over SOCKS</a>. So in this case, you won’t be able to use DNS as if you were inside the cluster, but instead have to rely on knowing private ip addresses.</p></section>
|
|
|
|
<div class="post-tags">
|
|
|
|
|
|
<nav class="nav tags">
|
|
<ul class="tags">
|
|
|
|
<li><a href="/tags/azure">azure</a></li>
|
|
|
|
<li><a href="/tags/database">database</a></li>
|
|
|
|
<li><a href="/tags/proxy">proxy</a></li>
|
|
|
|
<li><a href="/tags/socks">socks</a></li>
|
|
|
|
<li><a href="/tags/aks">aks</a></li>
|
|
|
|
<li><a href="/tags/k8s">k8s</a></li>
|
|
|
|
<li><a href="/tags/aws">aws</a></li>
|
|
|
|
<li><a href="/tags/bastion">bastion</a></li>
|
|
|
|
<li><a href="/tags/eks">eks</a></li>
|
|
|
|
<li><a href="/tags/cloud-sql-proxy">cloud-sql-proxy</a></li>
|
|
|
|
<li><a href="/tags/kubectl-plugin-socks5-proxy">kubectl-plugin-socks5-proxy</a></li>
|
|
|
|
</ul>
|
|
</nav>
|
|
|
|
|
|
</div>
|
|
</article>
|
|
</main>
|
|
|
|
<section id='comments' class='comments'>
|
|
<div class='container sep-before'>
|
|
<div class='comments'><script>
|
|
|
|
var getTheme = window.localStorage && window.localStorage.getItem("theme-storage");
|
|
getTheme = getTheme == null ? 'light' : getTheme;
|
|
|
|
let theme = getTheme === 'dark' ? 'github-dark' : 'github-light';
|
|
let s = document.createElement('script');
|
|
s.src = 'https://utteranc.es/client.js';
|
|
s.setAttribute('repo', 'davegallant\/davegallant.github.io');
|
|
s.setAttribute('issue-term', 'pathname');
|
|
s.setAttribute('theme', theme);
|
|
s.setAttribute('crossorigin', 'anonymous');
|
|
s.setAttribute('async', '');
|
|
document.querySelector('div.comments').innerHTML = '';
|
|
document.querySelector('div.comments').appendChild(s);
|
|
</script>
|
|
</div>
|
|
</div>
|
|
</section><footer>
|
|
<div style="display:flex"><a class="soc" href="https://github.com/davegallant" rel="me" title="GitHub"><i data-feather="github"></i></a>
|
|
<a class="border"></a><a class="soc" href="https://twitter.com/davega11ant/" rel="me" title="Twitter"><i data-feather="twitter"></i></a>
|
|
<a class="border"></a><a class="soc" href="https://mastodon.social/@davegallant" rel="me" title="Mastodon"><i data-feather="speaker"></i></a>
|
|
<a class="border"></a><a class="soc" href="https://www.linkedin.com/in/dave-gallant/" rel="me" title="LinkedIn"><i data-feather="linkedin"></i></a>
|
|
<a class="border"></a></div>
|
|
<div class="footer-info">
|
|
2023 Dave Gallant
|
|
</div>
|
|
</footer>
|
|
|
|
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>
|
|
<script>
|
|
var doNotTrack = false;
|
|
if (!doNotTrack) {
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
gtag('config', 'G-V8WJDERTX9', { 'anonymize_ip': false });
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
feather.replace()
|
|
</script></div>
|
|
</body>
|
|
</html>
|