From 25cd0030937d27a0c73f069ddf3f70f81ed4b654 Mon Sep 17 00:00:00 2001 From: vorakl Date: Thu, 18 Jan 2024 15:58:21 -0800 Subject: [PATCH] New content --- articles/udp-link/index.html | 8 ++++---- atom.xml | 19 ++++++++++--------- src.docs/content/articles/udp-link.rst | 19 ++++++++++--------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/articles/udp-link/index.html b/articles/udp-link/index.html index d11f18f4..b24118af 100644 --- a/articles/udp-link/index.html +++ b/articles/udp-link/index.html @@ -1,9 +1,9 @@ - Using udp-link to enhance TCP connections stability :: Vorakl's notes

Using udp-link to enhance TCP connections stability

on 2024-01-16 in article about networking tools ~4 min read

A UDP transport layer implementation for proxying TCP connections

I recently discovered udp-link, 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. udp-link 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.


udp-proxy is written in C by Pavlo Gulchuk, who has a lot of experience in running unreliable networks. Despite being a young project, the version v0.4 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.


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 127.0.0.1:22 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 udp-link uses a zero server-side configuration, all configuration tweaks happen only on the client side.


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. udp-link 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.


To start using udp-link, you need to clone the repository, compile, and install the tool on both sides

git clone https://github.com/pgul/udp-link.git
+ Using udp-link to enhance TCP connections stability :: Vorakl's notes   

Using udp-link to enhance TCP connections stability

on 2024-01-16 in article about networking tools ~4 min read

A UDP transport layer implementation for proxying TCP connections

I recently discovered udp-link, 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. udp-link 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.


udp-proxy is written in C by Pavlo Gulchuk, who has a lot of experience in running unreliable networks. Despite being a young project, the version v0.4 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.


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 127.0.0.1:22 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 udp-link uses a zero server-side configuration, all configuration tweaks happen only on the client side.


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. udp-link 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.


To start using udp-link, you need to clone the repository, compile, and install the tool on both sides

git clone https://github.com/pgul/udp-link.git
 cd  udp-link
 make
 sudo make install
 

and then make an ssh connection on the client side by executing a command similar to

ssh -o ProxyCommand="udp-link %r@%h" user@host
-

OpenSSH supports a number of macros such as %r and %p 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 'OpenSSH client side key management for better privacy and security', written by Timothée Ravier. So I'm actively using ssh_config files, where I specify all connection-specific details, such as hostname, username, ssh key, and in this case, ProxyCommand. My typical ssh_config file looks something like this

Host some-server
+

OpenSSH supports a number of macros such as %r and %p 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 'OpenSSH client side key management for better privacy and security', written by Timothée Ravier. So I'm actively using ssh_config files, where I specify all connection-specific details, such as hostname, username, ssh key, and in this case, ProxyCommand. My typical ssh_config file looks something like this

Host some-server
     user some-user
     hostname some-IP
     IdentityFile ~/.ssh/ssh-some-server.key
@@ -20,9 +20,9 @@
     HostbasedAuthentication no
     SendEnv no
 

and then to connect I just run

ssh some-server
-

The second Host some-IP block is needed to provide a correct ssh key to a temporary ssh connection that udp-link establishes at the beginning of the session. To debug the connection, I run

ssh -o ProxyCommand="udp-link --dump some-IP" some-server
+

The second Host some-IP block is needed to provide a correct ssh key to a temporary ssh connection (without ProxyCommand) that udp-link establishes at the beginning of a new session. To debug the connection add --debug option

ssh -o ProxyCommand="udp-link --dump some-IP" some-server
 

If I need to bind a connection to a specific UDP port on the server side, I initiate a connection like this

ssh -o ProxyCommand="udp-link -b 1234 some-IP" some-server
 

You can also bind it to a privileged port (1-1024), but udp-link 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.

chown root /usr/local/bin/udp-link
 chmod u+s /usr/local/bin/udp-link
-

Unlike other projects with a similar goal, e.g. Mosh, udp-link 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, udp-link cannot currently listen on a local TCP port on the client side. Fortunately, this can be worked around by adding socat and its exceptional ability to connect things. However, socat cannot be paired with udp-link 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 2525/TCP port on the client side, then proxy a future TCP connection over a UDP channel to a remote host, and connect it to a 25/TCP port on the server's localhost in debug mode

socat TCP-LISTEN:2525 SYSTEM:"udp-link -t 127.0.0.1\:25 --debug some-IP"
+

Unlike other projects with a similar goal, e.g. Mosh, udp-link 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, udp-link cannot currently listen on a local TCP port on the client side. Fortunately, this can be worked around by adding socat and its exceptional ability to connect things. However, socat cannot be paired with udp-link 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 2525/TCP port on the client side, then proxy a future TCP connection over a UDP channel to a remote host, and connect it to a 25/TCP port on the server's localhost in debug mode

socat TCP-LISTEN:2525 SYSTEM:"udp-link -t 127.0.0.1\:25 --debug some-IP"
 

udp-link is a small, flexible and very useful tool. I hope to see further development, adding new features and maturing the code base.

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.
\ No newline at end of file diff --git a/atom.xml b/atom.xml index 750bccc1..f119a5a9 100644 --- a/atom.xml +++ b/atom.xml @@ -40,8 +40,8 @@ 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 +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"> @@ -58,7 +58,7 @@ sudo make install 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 +<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 class="reference external" href="https://tim.siosm.fr/blog/2023/01/13/openssh-key-management/">OpenSSH client side key management for better privacy and security</a>', @@ -87,8 +87,8 @@ Host * <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> +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, @@ -106,14 +106,15 @@ chmod u+s /usr/local/bin/udp-link <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 +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 socat. Here is +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> diff --git a/src.docs/content/articles/udp-link.rst b/src.docs/content/articles/udp-link.rst index 84c6e00d..3fee5a9a 100644 --- a/src.docs/content/articles/udp-link.rst +++ b/src.docs/content/articles/udp-link.rst @@ -47,8 +47,8 @@ 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. *udp-link* doesn't -encrypt the transferred data, which is useful when is used together with ssh +This is where a secure client authentication comes into play. *udp-link* **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. @@ -71,7 +71,7 @@ similar to ssh -o ProxyCommand="udp-link %r@%h" user@host -OpenSSH supports a number of macros such as *%r* and *%p* which and can be found +OpenSSH supports a number of macros such as *%r* and *%p* 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 '`OpenSSH client side key management for better privacy and security`_', @@ -106,8 +106,8 @@ and then to connect I just run ssh some-server The second **Host some-IP** block is needed to provide a correct ssh key to -a temporary ssh connection that *udp-link* establishes at the beginning of -the session. To debug the connection, I run +a temporary ssh connection (without *ProxyCommand*) that *udp-link* establishes +at the beginning of a new session. To debug the connection add *--debug* option .. code-block:: shell @@ -133,14 +133,15 @@ of a binary file. | Unlike other projects with a similar goal, e.g. Mosh_, *udp-link* 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, *udp-link* cannot currently listen on a local TCP port on the client +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, *udp-link* cannot +currently listen on a local TCP port on the client side. Fortunately, this can be worked around by adding *socat* and its exceptional ability to connect things. However, *socat* cannot be paired with *udp-link* 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 +back from the network. The trick is that udp-link is called by *socat*. Here is an example of how to open a listening *2525/TCP* port on the client side, then proxy a future TCP connection over a UDP channel to a remote host, and connect it to a *25/TCP* port on the server's localhost in debug mode