Skip to content

Commit

Permalink
New content
Browse files Browse the repository at this point in the history
  • Loading branch information
vorakl committed Jan 18, 2024
1 parent 95c4b97 commit 25cd003
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 22 deletions.
8 changes: 4 additions & 4 deletions articles/udp-link/index.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!DOCTYPE html><html lang=en> <head><meta charset=utf-8><title>Using udp-link to enhance TCP connections stability :: Vorakl's notes</title><meta name=viewport content="width=device-width, initial-scale=1.0"><meta name=robots content=all><link href=https://vorakl.com/articles/udp-link/ rel=canonical><meta name=description content="A UDP transport layer implementation for proxying TCP connections"><link rel=stylesheet href="https://vorakl.com/theme/bootstrap-pygments.bundle.min.css?v=1705613139"><link rel=alternate type=application/atom+xml href=https://vorakl.com/atom.xml title="Vorakl's notes"><link rel="shortcut icon" href="/favicon.ico?v=1705613139"><meta name=apple-mobile-web-app-title content="Vorakl's notes"><meta name=application-name content="Vorakl's notes"></head> <body> <div class=navbar> <div class=navbar-inner> <div class=container> <a href=https://vorakl.com/ class=brand>Vorakl's notes</a> <div class=nav-collapse> <ul class="nav pull-right"> <!-- <li class="divider-vertical"></li> --> <li><a href=https://vorakl.com/pages/reading/ >Reading</a></li> <li><a href=https://vorakl.com/pages/projects/ >Projects</a></li> <li><a href=https://vorakl.com/pages/contacts/ >Contacts</a></li> <li><a href=https://vorakl.com/pages/about/ >About</a></li> <!-- <li class="divider-vertical"></li> --> </ul> </div> </div> </div> </div> <div class=container> <div class=content> <div class=row> <div class=span12> <div class=article> <div class=content-title> <h2>Using udp-link to enhance TCP connections stability</h2> <div class="well small">on 2024-01-16 in <a href=https://vorakl.com/categories/article/ >article</a> about <a href=https://vorakl.com/tags/networking/ >networking</a> <a href=https://vorakl.com/tags/tools/ >tools</a> ~4 min read </div> <p><h3>A UDP transport layer implementation for proxying TCP connections</h3></p> </div> <div class=content><p>I recently discovered <a class="reference external" href=https://github.com/pgul/udp-link>udp-link</a>, a very useful project for all those guys like me who spend most of their working time in terminals over ssh connections. The tool implements the UDP transport layer, which acts as a proxy for TCP connections. It's designed to be integrated into the OpenSSH configuration. However, with a little trick, it can also be used as a general-purpose TCP-over-UDP proxy. <em>udp-link</em> greatly improves the stability of connections over unreliable networks that experience packet loss and intermittent connectivity. It also includes an IP roaming, which allows TCP connections to remain alive even if an IP address changes.</p> <div class=line-block> <div class=line><br></div> </div> <p>udp-proxy is written in C by <a class="reference external" href=https://gul.kiev.ua>Pavlo Gulchuk</a>, who has a lot of experience in running unreliable networks. Despite being a young project, the version <a class="reference external" href=https://github.com/pgul/udp-link/releases/tag/v0.4>v0.4</a> shows pretty stable results. It's quite fast, and once configured, you don't have to think about it anymore. Unless you're surprised every time when ssh connections don't brake, survive a laptop's sleep mode and connections to different Wi-Fi networks.</p> <div class=line-block> <div class=line><br></div> </div> <p>The current architecture is fairly simple. The tool on the client side takes data on the stdin and sends it via UDP to the server side where the same copy of the tool takes that data from the network and sends it over to some TCP service. The destination TCP service and a UDP listening port on the server side can be specified on the client at startup. Otherwise, a TCP connection will be established with <em>127.0.0.1:22</em> and a port is randomly chosen from a predefined port range. Note that the server firewall should allow the traffic to this port range on UDP. The TCP service can also reside on a remote host, if the server side is used as a jumpbox. I consider it one of the greatest features that <em>udp-link</em> uses a zero server-side configuration, all configuration tweaks happen only on the client side.</p> <div class=line-block> <div class=line><br></div> </div> <p>udp-link on the server side does not run as a daemon or listen on a UDP port all the time. Instead, the client invokes the tool in a server mode with a randomly generated key that is used to authenticate a client connection. This is done on demand by establishing a temporary ssh connection to the server side and running the tool in the background, after which a connection is terminated. This is where a secure client authentication comes into play. <em>udp-link</em> doesn't encrypt the transferred data, which is useful when is used together with ssh because it avoids a double encryption, but needs to be kept that in mind when used with other configurations.</p> <div class=line-block> <div class=line><br></div> </div> <p>To start using <em>udp-link</em>, you need to clone the repository, compile, and install the tool on both sides</p> <div class=highlight><pre><span></span>git clone https://github.com/pgul/udp-link.git
<!DOCTYPE html><html lang=en> <head><meta charset=utf-8><title>Using udp-link to enhance TCP connections stability :: Vorakl's notes</title><meta name=viewport content="width=device-width, initial-scale=1.0"><meta name=robots content=all><link href=https://vorakl.com/articles/udp-link/ rel=canonical><meta name=description content="A UDP transport layer implementation for proxying TCP connections"><link rel=stylesheet href="https://vorakl.com/theme/bootstrap-pygments.bundle.min.css?v=1705613139"><link rel=alternate type=application/atom+xml href=https://vorakl.com/atom.xml title="Vorakl's notes"><link rel="shortcut icon" href="/favicon.ico?v=1705613139"><meta name=apple-mobile-web-app-title content="Vorakl's notes"><meta name=application-name content="Vorakl's notes"></head> <body> <div class=navbar> <div class=navbar-inner> <div class=container> <a href=https://vorakl.com/ class=brand>Vorakl's notes</a> <div class=nav-collapse> <ul class="nav pull-right"> <!-- <li class="divider-vertical"></li> --> <li><a href=https://vorakl.com/pages/reading/ >Reading</a></li> <li><a href=https://vorakl.com/pages/projects/ >Projects</a></li> <li><a href=https://vorakl.com/pages/contacts/ >Contacts</a></li> <li><a href=https://vorakl.com/pages/about/ >About</a></li> <!-- <li class="divider-vertical"></li> --> </ul> </div> </div> </div> </div> <div class=container> <div class=content> <div class=row> <div class=span12> <div class=article> <div class=content-title> <h2>Using udp-link to enhance TCP connections stability</h2> <div class="well small">on 2024-01-16 in <a href=https://vorakl.com/categories/article/ >article</a> about <a href=https://vorakl.com/tags/networking/ >networking</a> <a href=https://vorakl.com/tags/tools/ >tools</a> ~4 min read </div> <p><h3>A UDP transport layer implementation for proxying TCP connections</h3></p> </div> <div class=content><p>I recently discovered <a class="reference external" href=https://github.com/pgul/udp-link>udp-link</a>, a very useful project for all those guys like me who spend most of their working time in terminals over ssh connections. The tool implements the UDP transport layer, which acts as a proxy for TCP connections. It's designed to be integrated into the OpenSSH configuration. However, with a little trick, it can also be used as a general-purpose TCP-over-UDP proxy. <em>udp-link</em> greatly improves the stability of connections over unreliable networks that experience packet loss and intermittent connectivity. It also includes an IP roaming, which allows TCP connections to remain alive even if an IP address changes.</p> <div class=line-block> <div class=line><br></div> </div> <p>udp-proxy is written in C by <a class="reference external" href=https://gul.kiev.ua>Pavlo Gulchuk</a>, who has a lot of experience in running unreliable networks. Despite being a young project, the version <a class="reference external" href=https://github.com/pgul/udp-link/releases/tag/v0.4>v0.4</a> shows pretty stable results. It's quite fast, and once configured, you don't have to think about it anymore. Unless you're surprised every time when ssh connections don't brake, survive a laptop's sleep mode and connections to different Wi-Fi networks.</p> <div class=line-block> <div class=line><br></div> </div> <p>The current architecture is fairly simple. The tool on the client side takes data on the stdin and sends it via UDP to the server side where the same copy of the tool takes that data from the network and sends it over to some TCP service. The destination TCP service and a UDP listening port on the server side can be specified on the client at startup. Otherwise, a TCP connection will be established with <em>127.0.0.1:22</em> and a port is randomly chosen from a predefined port range. Note that the server firewall should allow the traffic to this port range on UDP. The TCP service can also reside on a remote host, if the server side is used as a jumpbox. I consider it one of the greatest features that <em>udp-link</em> uses a zero server-side configuration, all configuration tweaks happen only on the client side.</p> <div class=line-block> <div class=line><br></div> </div> <p>udp-link on the server side does not run as a daemon or listen on a UDP port all the time. Instead, the client invokes the tool in a server mode with a randomly generated key that is used to authenticate a client connection. This is done on demand by establishing a temporary ssh connection to the server side and running the tool in the background, after which a connection is terminated. This is where a secure client authentication comes into play. <em>udp-link</em> <strong>doesn't encrypt the transferred data</strong>, which is useful when is used together with ssh because it avoids a double encryption, but needs to be kept that in mind when used with other configurations.</p> <div class=line-block> <div class=line><br></div> </div> <p>To start using <em>udp-link</em>, you need to clone the repository, compile, and install the tool on both sides</p> <div class=highlight><pre><span></span>git clone https://github.com/pgul/udp-link.git
<span class=nb>cd</span> udp-link
make
sudo make install
</pre></div> <p>and then make an ssh connection on the client side by executing a command similar to</p> <div class=highlight><pre><span></span>ssh -o <span class=nv>ProxyCommand</span><span class=o>=</span><span class=s2>&quot;udp-link %r@%h&quot;</span> user@host
</pre></div> <p>OpenSSH supports a number of macros such as <em>%r</em> and <em>%p</em> which and can be found in its documentation. Personally, I use ssh in a slightly different way and never send out my public ssh keys to unknown hosts. More details on this topic can be found in a great article '<a href=https://tim.siosm.fr/blog/2023/01/13/openssh-key-management/ class="reference external">OpenSSH client side key management for better privacy and security</a>', written by Timothée Ravier. So I'm actively using <em>ssh_config</em> files, where I specify all connection-specific details, such as hostname, username, ssh key, and in this case, <strong>ProxyCommand</strong>. My typical <em>ssh_config</em> file looks something like this</p> <div class=highlight><pre><span></span>Host some-server
</pre></div> <p>OpenSSH supports a number of macros such as <em>%r</em> and <em>%p</em> which can be found in its documentation. Personally, I use ssh in a slightly different way and never send out my public ssh keys to unknown hosts. More details on this topic can be found in a great article '<a href=https://tim.siosm.fr/blog/2023/01/13/openssh-key-management/ class="reference external">OpenSSH client side key management for better privacy and security</a>', written by Timothée Ravier. So I'm actively using <em>ssh_config</em> files, where I specify all connection-specific details, such as hostname, username, ssh key, and in this case, <strong>ProxyCommand</strong>. My typical <em>ssh_config</em> file looks something like this</p> <div class=highlight><pre><span></span>Host some-server
user some-user
hostname some-IP
IdentityFile ~/.ssh/ssh-some-server.key
Expand All @@ -20,9 +20,9 @@
HostbasedAuthentication no
SendEnv no
</pre></div> <p>and then to connect I just run</p> <div class=highlight><pre><span></span>ssh some-server
</pre></div> <p>The second <strong>Host some-IP</strong> block is needed to provide a correct ssh key to a temporary ssh connection that <em>udp-link</em> establishes at the beginning of the session. To debug the connection, I run</p> <div class=highlight><pre><span></span>ssh -o <span class=nv>ProxyCommand</span><span class=o>=</span><span class=s2>&quot;udp-link --dump some-IP&quot;</span> some-server
</pre></div> <p>The second <strong>Host some-IP</strong> block is needed to provide a correct ssh key to a temporary ssh connection (without <em>ProxyCommand</em>) that <em>udp-link</em> establishes at the beginning of a new session. To debug the connection add <em>--debug</em> option</p> <div class=highlight><pre><span></span>ssh -o <span class=nv>ProxyCommand</span><span class=o>=</span><span class=s2>&quot;udp-link --dump some-IP&quot;</span> some-server
</pre></div> <p>If I need to bind a connection to a specific UDP port on the server side, I initiate a connection like this</p> <div class=highlight><pre><span></span>ssh -o <span class=nv>ProxyCommand</span><span class=o>=</span><span class=s2>&quot;udp-link -b 1234 some-IP&quot;</span> some-server
</pre></div> <p>You can also bind it to a privileged port (1-1024), but <em>udp-link</em> needs root permissions to do this, which can be achieved in a number of ways, such as making it root-owned with the setuid bit turned on on the server-side copy of a binary file.</p> <div class=highlight><pre><span></span>chown root /usr/local/bin/udp-link
chmod u+s /usr/local/bin/udp-link
</pre></div> <div class=line-block> <div class=line><br></div> </div> <p>Unlike other projects with a similar goal, e.g. <a class="reference external" href=https://github.com/mobile-shell/mosh>Mosh</a>, <em>udp-link</em> doesn't allocate a pesudo terminal, which I consider a feature, because it opens the possibility to use the tool for proxying any arbitrary TCP connection. However, <em>udp-link</em> cannot currently listen on a local TCP port on the client side. Fortunately, this can be worked around by adding <em>socat</em> and its exceptional ability to connect things. However, <em>socat</em> cannot be paired with <em>udp-link</em> via an unnamed pipe, because pipes provide a unidirectional interprocess communication, while here we need a bi-directional communication to get data back from the network. The trick is that udp-link is called by socat. Here is an example of how to open a listening <em>2525/TCP</em> port on the client side, then proxy a future TCP connection over a UDP channel to a remote host, and connect it to a <em>25/TCP</em> port on the server's localhost in debug mode</p> <div class=highlight><pre><span></span>socat TCP-LISTEN:2525 SYSTEM:<span class=s2>&quot;udp-link -t 127.0.0.1\:25 --debug some-IP&quot;</span>
</pre></div> <div class=line-block> <div class=line><br></div> </div> <p>Unlike other projects with a similar goal, e.g. <a class="reference external" href=https://github.com/mobile-shell/mosh>Mosh</a>, <em>udp-link</em> doesn't allocate a pseudo terminal, which I consider a feature, because it opens the possibility to use the tool not only for accessing remote terminals, but also for proxying any arbitrary TCP connection. However, <em>udp-link</em> cannot currently listen on a local TCP port on the client side. Fortunately, this can be worked around by adding <em>socat</em> and its exceptional ability to connect things. However, <em>socat</em> cannot be paired with <em>udp-link</em> via an unnamed pipe, because pipes provide a unidirectional interprocess communication, while here we need a bi-directional communication to get data back from the network. The trick is that udp-link is called by <em>socat</em>. Here is an example of how to open a listening <em>2525/TCP</em> port on the client side, then proxy a future TCP connection over a UDP channel to a remote host, and connect it to a <em>25/TCP</em> port on the server's localhost in debug mode</p> <div class=highlight><pre><span></span>socat TCP-LISTEN:2525 SYSTEM:<span class=s2>&quot;udp-link -t 127.0.0.1\:25 --debug some-IP&quot;</span>
</pre></div> <div class=line-block> <div class=line><br></div> </div> <p><em>udp-link</em> is a small, flexible and very useful tool. I hope to see further development, adding new features and maturing the code base.</p> <!-- Links --> </div> </div> <div class=article> <div class="well small"><h5>This is my personal blog. All ideas, opinions, examples, and other information that can be found here are my own and belong entirely to me. This is the result of my personal efforts and activities at my free time. It doesn't relate to any professional work I've done and doesn't have correlations with any companies I worked for, I'm currently working, or will work in the future.</h5></div> </div> </div> </div> </div> <footer> <div class=container> <div class=row> <div class=span5> <span class=pull-left> &copy; 2024 <a href=https://vorakl.com/pages/about/ >vorakl</a> All Rights Reserved </span> </div> <div class=span7> <div class=pull-right> Powered by <a href=https://github.com/getpelican/pelican>Pelican</a> and <a href=https://github.com/vorakl/aves>Aves</a> theme </div> </div> </div> </div> </footer> </div> </body> </html>
Loading

0 comments on commit 25cd003

Please sign in to comment.