<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Articles by Giovanni Tommasini]]></title><description><![CDATA[Enthusiastic Seeker.
I love to constantly improve my freedom; I love challenges and I like to keep improving myself in personal life as in work.]]></description><link>https://blog.gt0.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1619346352995/YYT5yEjBU.png</url><title>Articles by Giovanni Tommasini</title><link>https://blog.gt0.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 21:35:08 GMT</lastBuildDate><atom:link href="https://blog.gt0.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Come unire un Video e Audio]]></title><description><![CDATA[Il problema
È una situazione in cui molti di noi si sono ritrovati - hai due file separati, uno con il contenuto video che desideri, e l'altro che contiene l'audio corrispondente. Forse hai scaricato un film muto e una traccia di commento separata, o...]]></description><link>https://blog.gt0.dev/come-unire-un-video-e-audio</link><guid isPermaLink="true">https://blog.gt0.dev/come-unire-un-video-e-audio</guid><category><![CDATA[merge]]></category><category><![CDATA[video]]></category><category><![CDATA[audio]]></category><category><![CDATA[Video Editing App]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Wed, 14 Jun 2023 13:13:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/iKdQCIiSMlQ/upload/0b78b4708b76a9eb0728aae3e3817542.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-il-problema">Il problema</h1>
<p>È una situazione in cui molti di noi si sono ritrovati - hai due file separati, uno con il contenuto video che desideri, e l'altro che contiene l'audio corrispondente. Forse hai scaricato un film muto e una traccia di commento separata, o hai registrato una presentazione e l'audio separatamente. Qualunque sia il caso, ora ti trovi di fronte al compito di unire questi due in un unico file coeso. In questo post, esploreremo come fare esattamente questo utilizzando lo strumento FFmpeg.</p>
<h1 id="heading-lanalisi">L'analisi</h1>
<p>FFmpeg è un software libero e open source che consente di manipolare file multimediali. Può convertire audio e video in quasi qualsiasi formato, ed è molto utilizzato per lo streaming di video e audio.</p>
<h1 id="heading-la-soluzione">La soluzione</h1>
<p>Il comando che utilizzeremo oggi è il seguente:</p>
<pre><code class="lang-bash">ffmpeg -i video.mp4 -i audio.mp4 -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
</code></pre>
<p>Ora, facciamo un'analisi dettagliata di questo comando:</p>
<ol>
<li><p><code>ffmpeg</code>: È il comando che avvia il programma FFmpeg.</p>
</li>
<li><p><code>-i video.mp4 -i audio.mp4</code>: Questi sono i file di input. Il primo <code>-i video.mp4</code> indica a FFmpeg che <code>video.mp4</code> è il nostro file video di input, mentre il secondo <code>-i audio.mp4</code> indica che <code>audio.mp4</code> è il nostro file audio di input.</p>
</li>
<li><p><code>-c:v copy -c:a aac</code>: Queste opzioni definiscono i codec che vogliamo utilizzare. <code>-c:v copy</code> dice a FFmpeg di copiare il codec video originale. <code>-c:a aac</code> dice a FFmpeg di usare il codec audio AAC per il file di output.</p>
</li>
<li><p><code>-map 0:v:0 -map 1:a:0</code>: Questi comandi mappano i flussi di input al file di output. <code>-map 0:v:0</code> dice a FFmpeg di prendere il primo flusso video (v:0) dal primo file di input (0) e <code>-map 1:a:0</code> dice di prendere il primo flusso audio (a:0) dal secondo file di input (1).</p>
</li>
<li><p><code>output.mp4</code>: Questo è il nome del file di output. Il file risultante sarà un file .mp4 con il video dal primo file di input e l'audio dal secondo file di input.</p>
</li>
</ol>
<p>Ecco fatto! Con un solo comando, potete unire un video con un audio. Spero che questo post vi sia stato utile. Se avete domande o commenti, non esitate a lasciarli qui sotto.</p>
]]></content:encoded></item><item><title><![CDATA[Merging Video and Audio]]></title><description><![CDATA[The problem
It's a situation many of us have found ourselves in - you have two separate files, one with the video content you want, and the other containing the corresponding audio. Perhaps you've downloaded a silent film and a separate commentary tr...]]></description><link>https://blog.gt0.dev/merging-video-and-audio</link><guid isPermaLink="true">https://blog.gt0.dev/merging-video-and-audio</guid><category><![CDATA[Video Editing App]]></category><category><![CDATA[merging audio video]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Wed, 14 Jun 2023 13:11:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/yk9VXp4W5-Q/upload/60d2739de7a8b488ca722ebda5787586.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-the-problem"><strong>The problem</strong></h1>
<p>It's a situation many of us have found ourselves in - you have two separate files, one with the video content you want, and the other containing the corresponding audio. Perhaps you've downloaded a silent film and a separate commentary track, or you've recorded a presentation and the audio separately. Whatever the case may be, you're now faced with the task of merging these two into a single, cohesive file. In this blog post, we'll explore how to do exactly that using the FFmpeg tool.</p>
<h1 id="heading-the-analysis"><strong>The analysis</strong></h1>
<p>FFmpeg is a free and open-source software that allows you to manipulate multimedia files. It can convert audio and video into almost any format, and it is widely used for video and audio streaming.</p>
<h1 id="heading-the-solution"><strong>The solution</strong></h1>
<p>The command we will be using today is as follows:</p>
<pre><code class="lang-bash">ffmpeg -i video.mp4 -i audio.mp4 -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 output.mp4
</code></pre>
<p>Now, let's do a detailed analysis of this command:</p>
<ol>
<li><p><code>ffmpeg</code>: This is the command that starts the FFmpeg program.</p>
</li>
<li><p><code>-i video.mp4 -i audio.mp4</code>: These are the input files. The first <code>-i video.mp4</code> tells FFmpeg that <code>video.mp4</code> is our input video file, while the second <code>-i audio.mp4</code> tells FFmpeg that <code>audio.mp4</code> is our input audio file.</p>
</li>
<li><p><code>-c:v copy -c:a aac</code>: These options define the codecs we want to use. <code>-c:v copy</code> tells FFmpeg to copy the original video codec. <code>-c:a aac</code> tells FFmpeg to use the AAC audio codec for the output file.</p>
</li>
<li><p><code>-map 0:v:0 -map 1:a:0</code>: These commands map the input streams to the output file. <code>-map 0:v:0</code> tells FFmpeg to take the first video stream (v:0) from the first input file (0) and <code>-map 1:a:0</code> tells FFmpeg to take the first audio stream (a:0) from the second input file (1).</p>
</li>
<li><p><code>output.mp4</code>: This is the name of the output file. The resulting file will be a .mp4 file with the video from the first input file and the audio from the second input file.</p>
</li>
</ol>
<p>And there you have it! With a single command, you can merge a video with an audio. I hope this post has been helpful. If you have any questions or comments, don't hesitate to leave them below.</p>
<p>Cheers!</p>
]]></content:encoded></item><item><title><![CDATA[Linux user with limited permissions]]></title><description><![CDATA[The idea and the purpose
In this article I want to answer this question: How can I restrict the normal user to run only limited set of commands.
So I describe step-by-step the method to create a linux user able to access to the console of a linux ser...]]></description><link>https://blog.gt0.dev/linux-user-with-limited-permissions</link><guid isPermaLink="true">https://blog.gt0.dev/linux-user-with-limited-permissions</guid><category><![CDATA[Linux]]></category><category><![CDATA[permissions]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysadmin]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Fri, 02 Sep 2022 13:01:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/4Mw7nkQDByk/upload/v1662121728266/DIF6NHOi6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-the-idea-and-the-purpose">The idea and the purpose</h1>
<p>In this article I want to answer this question: <em>How can I restrict the normal user to run only limited set of commands</em>.</p>
<p>So I describe <em>step-by-step</em> the method to create a linux user able to access to the console of a linux server but with limited permission to run commands.
This method is useful when, for example, you want to give access to one of your collaborators without risking that he can launch commands as an administrator.</p>
<p>The idea is to use the <a target="_blank" href="https://www.gnu.org/software/bash/manual/html_node/The-Restricted-Shell.html">restricted shell</a> <code>rbash</code> and declare which commands the user are able to run.</p>
<hr />

<h1 id="heading-the-step-by-step-guide">The step-by-step guide</h1>
<ol>
<li><p>create the new user</p>
<pre><code class="lang-bash">adduser &lt;username&gt;
</code></pre>
<p>compile all the requested fields. The most important is the password that will be used to access the server (for example in SSH).</p>
</li>
<li><p>set the <code>rbash</code> as shell for the new user</p>
<pre><code class="lang-bash">chsh -s /bin/rbash &lt;username&gt;
</code></pre>
</li>
<li><p>create a bin directory under the user home directory</p>
<pre><code class="lang-bash">mkdir /home/&lt;username&gt;/bin
chmod 755 /home/&lt;username&gt;/bin/
</code></pre>
</li>
<li><p>change the user's default PATH to the bin directory</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"PATH=<span class="hljs-variable">$HOME</span>/bin"</span> &gt;&gt; /home/&lt;username&gt;/.bashrc
<span class="hljs-built_in">echo</span> <span class="hljs-string">"export PATH"</span> &gt;&gt; /home/&lt;username&gt;/.bashrc
</code></pre>
</li>
<li><p>create symlinks of the command(s) that the user require to bin directory under the user home directory</p>
<pre><code class="lang-bash">ln -s /bin/ping /home/&lt;username&gt;/bin/
ln -s /bin/traceroute /home/&lt;username&gt;/bin/
ln -s /bin/htop /home/&lt;username&gt;/bin/
ln -s /bin/top /home/&lt;username&gt;/bin/
ln -s /bin/df /home/&lt;username&gt;/bin/
ln -s /bin/bmon /home/&lt;username&gt;/bin/
ln -s /bin/ps /home/&lt;username&gt;/bin/
ln -s /bin/date /home/&lt;username&gt;/bin/
ln -s /bin/netstat /home/&lt;username&gt;/bin/
ln -s /bin/free /home/&lt;username&gt;/bin/
</code></pre>
</li>
<li><p>restrict the user from modifying <code>~/.bashrc</code></p>
<pre><code class="lang-bash">chattr +i /home/&lt;username&gt;/.bashrc
</code></pre>
</li>
</ol>
<p>These are the basic steps to achieve the purpose.
However, I want to add one more of non-core but stylistic step: print the list of available commands when the user login in console.
For this purpose I user <a target="_blank" href="https://en.wikipedia.org/wiki/Message_of_the_day">motd</a>.</p>
<ol>
<li><p>create motd <code>99-available-commands</code> </p>
<pre><code class="lang-bash">touch /etc/update-motd.d/99-available-commands
</code></pre>
</li>
<li><p>add the list of available commands</p>
<pre><code class="lang-bash">cat &lt;&lt; EOF &gt;&gt; /etc/update-motd.d/99-available-commands
<span class="hljs-comment">#!/bin/sh</span>
<span class="hljs-built_in">export</span> TERM=xterm-256color
<span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-subst">$(tput setaf 4)</span>-------------------------------------------------------------------------------
-- Available commands:
-------------------------------------------------------------------------------<span class="hljs-subst">$(tput setaf 7)</span>
bmon          - Bandwidth monitor and rate estimator
date          - Display the current time or system date
df            - Report file system disk space usage
free          - Display amount of free and used memory in the system
htop          - Interactive process viewer
netstat       - Display ethernet and protocol info and statistics
ping          - Verify IP level connectivity
ps            - Display information about running processes
top           - Display Linux processes
traceroute    - Trace the path/hop from one network to another
<span class="hljs-subst">$(tput setaf 4)</span>-------------------------------------------------------------------------------<span class="hljs-subst">$(tput setaf 7)</span>
"</span>
EOF
</code></pre>
</li>
<li><p>set the right permission to the file</p>
<pre><code class="lang-bash">chmod 755 /etc/update-motd.d/99-available-commands
</code></pre>
</li>
</ol>
<p>Now the user when logging in will see a list of enabled commands like this
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662106238212/yOB8bWzGl.png" alt="image.png" /></p>
<hr />

<h1 id="heading-thanks-to">Thanks to</h1>
<ul>
<li><a target="_blank" href="https://stackoverflow.com/users/7323888/victor-wong">Victor Wong</a> for you comment in <a target="_blank" href="https://stackoverflow.com/questions/21498667/how-to-limit-user-commands-in-linux">this StackOverflow discussion</a></li>
<li>my <a target="_blank" href="https://evoseed.io/">evoseed</a> team</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Asterisk 11.6 and PostgreSQL 13: column d.adsrc does not exist]]></title><description><![CDATA[The problem
Do you work with asterisk 11.6 and PostgreSQL 9?Have you decided to upgrade PostgreSQL to version 13 and now Asterisk gives you bad errors at startup and most important no longer saves any lines in the CDRs?  
ERROR[12558] res_config_pgsq...]]></description><link>https://blog.gt0.dev/asterisk-116-and-postgresql-13-column-dadsrc-does-not-exist</link><guid isPermaLink="true">https://blog.gt0.dev/asterisk-116-and-postgresql-13-column-dadsrc-does-not-exist</guid><category><![CDATA[Voice]]></category><category><![CDATA[Bugs and Errors]]></category><category><![CDATA[PostgreSQL]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Wed, 06 Apr 2022 08:57:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/Fi_nhg5itCw/upload/v1649233706993/Kul8_y2iU.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-the-problem">The problem</h1>
<p>Do you work with <code>asterisk 11.6</code> and <code>PostgreSQL 9</code>?<br />Have you decided to upgrade PostgreSQL to version <code>13</code> and now Asterisk gives you <strong>bad errors</strong> at startup and most important <strong>no longer saves</strong> any lines in the <strong>CDRs</strong>?  </p>
<pre><code class="lang-bash">ERROR[12558] res_config_pgsql.c: PostgreSQL RealTime: Query Failed: SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace AND c.relname = <span class="hljs-string">'sipfriends'</span> AND n.nspname = current_schema()) INNER JOIN pg_catalog.pg_attribute a ON (NOT a.attisdropped) AND a.attnum &gt; 0 AND a.attrelid = c.oid) INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum ORDER BY n.nspname, c.relname, attnum
ERROR[12558] res_config_pgsql.c: PostgreSQL RealTime: Query Failed because: ERRORE:  the d.adsrc column does not exist
ERROR[12558] res_config_pgsql.c: Failed to query database columns <span class="hljs-keyword">for</span> table sipfriends
ERROR[12558] cdr_pgsql.c: Failed to query database columns: ERRORE:  the d.adsrc column does not exist
</code></pre>
<p>I found myself in this situation and I want to tell you how I got out of it.</p>
<hr />
<h1 id="heading-the-analysis">The analysis</h1>
<p>Googling I found the problem: some asterisk files (<code>cdr/cdr_pgsql.c</code>, <code>cel/cel_pgsql.c</code> and <code>res/res_config_pgsql.c</code>) query various system tables (such as <code>pg_class</code>, <code>pg_type</code>, <code>pg_attribute</code>) including in the select also the column <code>d.adsrc</code> (<code>d</code> is <code>pg_attrdef</code> table) but <strong>PostgreSQL 12 finally removed column adsrc from table pg_catalog.pg_attrdef (column default values), which has been deprecated since version 8.0</strong>.</p>
<p>The problem is well described:</p>
<ul>
<li>in the post on this mailing list: <a target="_blank" href="http://lists.digium.com/pipermail/asterisk-bugs/2019-October/196852.html">cdr_pgsql: accesses obsolete (and finally removed) column</a></li>
<li>in the reference <a target="_blank" href="https://issues.asterisk.org/jira/browse/ASTERISK-28571">asterisk Jira task</a></li>
</ul>
<p>As described in the task on gerrit: <em>fortunately, the same information which once was stored in adsrc is accessable via column adbin and function pg_catalog.pg_get_expr, which is the recommended way since PostgreSQL 8.0</em>. 
So here is the patch: <a target="_blank" href="https://gerrit.asterisk.org/c/asterisk/+/13027/">https://gerrit.asterisk.org/c/asterisk/+/13027/</a></p>
<hr />
<h1 id="heading-the-solution">The solution</h1>
<p>So for me the possible ways were mainly 3:</p>
<ol>
<li>upgrade Asterisk to the latest version, hoping (or rather, reading all the changelogs) that the problem would not occur there;</li>
<li>downgrade PostgreSQL to a version earlier than 11;</li>
<li>recompile Asterisk 11.6 with the patch indicated in the asterisk task.</li>
</ol>
<p>Of course, the best thing is to always have up-to-date systems, maybe not at the latest version but at the latest stable version; so thinking of keeping Asterisk 11.6 or downgrading PostgreSQL are not the best choices.<br />At the same time, it is true that jumping from Asterisk 11.6 to Asterisk 18 is not easy and before putting the system into production with Asterisk 18 I would have had to do many tests; instead I had little time and I needed to restore the full functionality of the voice system.<br />I decided to opt for the third choice <em>recompile asterisk 11.6 with the patch indicated in the asterisk task</em> and here I will describe the steps I have successfully followed. </p>
<p>The steps that I followed are easy and with more or less 0 downtime for the customers</p>
<pre><code class="lang-bash"><span class="hljs-comment"># I git clone the asterisk source code in tmp folder </span>
<span class="hljs-comment"># and checkout the 11.6 version</span>
<span class="hljs-built_in">cd</span> /tmp
git <span class="hljs-built_in">clone</span> https://github.com/asterisk/asterisk.git
<span class="hljs-built_in">cd</span> asterisk
git checkout certified/11.6
<span class="hljs-comment"># I install the needed packages</span>
<span class="hljs-comment"># You can also use the install_prereq (take a look at Linkography section)</span>
apt-get install ncurses-dev libxml2-dev sqlite3 libsqlite3-dev libpq-dev
<span class="hljs-comment"># I configure the installation</span>
./configure
make menuselect <span class="hljs-comment"># remember to select all the module and functions you need</span>
<span class="hljs-comment"># I ran the patch by editing these files</span>
vim cdr/cdr_pgsql.c <span class="hljs-comment"># https://gerrit.asterisk.org/c/asterisk/+/13027/2/cdr/cdr_pgsql.c</span>
vim cel/cel_pgsql.c <span class="hljs-comment"># https://gerrit.asterisk.org/c/asterisk/+/13027/2/cel/cel_pgsql.c</span>
vim res/res_config_pgsql.c <span class="hljs-comment"># https://gerrit.asterisk.org/c/asterisk/+/13027/2/res/res_config_pgsql.c</span>
<span class="hljs-comment"># I lunch the make</span>
make
<span class="hljs-comment"># I remove the actual asterisk installation</span>
apt-get remove asterisk asterisk asterisk-config asterisk-core-sounds-en asterisk-core-sounds-en-gsm asterisk-moh-opsound-gsm asterisk-modules
<span class="hljs-comment"># and in the end I install the compiled and patched version</span>
make install
</code></pre>
<p>If your system consists of several asterisk nodes, one clone of the other (i.e. with the same OS), you do not need to compile asterisk on each node to update any additional asterisk nodes, but you can follow these steps</p>
<ol>
<li><p>go to the asterisk node where you recompiled and create an archive of the asterisk folder</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> /tmp
 tar -cvzf asterisk11-6-patched.tar.gz asterisk
</code></pre>
</li>
<li><p>move the <code>tar.gz</code> on the asterisk node to be patched</p>
</li>
<li><p>decompress the <code>tar.gz</code>, remove the current version of asterisk and install the patched one</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> /tmp
 tar -xvzf asterisk11-6-patched.tar.gz
 <span class="hljs-built_in">cd</span> asterisk
 apt-get install build-essential
 apt-get remove asterisk asterisk-config asterisk-core-sounds-en asterisk-core-sounds-en-gsm asterisk-moh-opsound-gsm asterisk-modules
 make install
</code></pre>
</li>
</ol>
<p>Start asterisk, make a call and check your CDR. <strong>You will see that the data is there now!</strong></p>
<hr />
<h1 id="heading-linkography">Linkography</h1>
<ul>
<li><a target="_blank" href="https://wiki.asterisk.org/wiki/display/AST/Building+and+Installing+Asterisk">Compile asterisk</a></li>
<li><a target="_blank" href="https://wiki.asterisk.org/wiki/display/AST/Checking+Asterisk+Requirements#CheckingAsteriskRequirements-install_prereq">Install the needed software for asterisk compiling</a></li>
<li><a target="_blank" href="http://lists.digium.com/pipermail/asterisk-bugs/2019-October/196852.html">Mailinglist post</a></li>
<li><a target="_blank" href="https://issues.asterisk.org/jira/browse/ASTERISK-28571">Asterisk Jira task</a></li>
<li><a target="_blank" href="https://gerrit.asterisk.org/c/asterisk/+/13027">Asterisk patch commit</a></li>
<li><a target="_blank" href="https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=fe5038236c6b99d48c2faa2247b5cec9703add2a">PostgreSQL remove adsrc commit</a></li>
</ul>
<p>Cheers!</p>
]]></content:encoded></item><item><title><![CDATA[VoIP calls and TLS security]]></title><description><![CDATA[After a while, here I am again, talking about VoIP.The last article is about audio problems and the quality of a VoIP call. In this new article, I talk about VoIP over TLS and in particular how to configure a SIP server with self-renewing TLS certifi...]]></description><link>https://blog.gt0.dev/voip-calls-and-tls-security</link><guid isPermaLink="true">https://blog.gt0.dev/voip-calls-and-tls-security</guid><category><![CDATA[TLS]]></category><category><![CDATA[Voice]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Wed, 16 Mar 2022 17:41:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/pS9ssjTQOM0/upload/v1647450129330/S8uyjpqB6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After a while, here I am again, talking about VoIP.<br />The last article is about <a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-6-audio-problems-and-the-quality-of-a-voip-call">audio problems and the quality of a VoIP call</a>. In this new article, I talk about VoIP over TLS and in particular how to configure a SIP server with self-renewing TLS certificates.</p>
<p>This is an article accompanying code found in this <a target="_blank" href="https://github.com/evoseed/kamailio-tls-letsencrypt">github repo</a>.</p>
<h2 id="heading-the-idea-and-the-purpose">The idea and the purpose</h2>
<p>The purpose of this article is to explain how to deal with SIP over TSL. In the <a target="_blank" href="https://github.com/evoseed/kamailio-tls-letsencrypt">this github repo</a> the evoseed team explains a simple way to deploy a Kamailio server in a docker container with TLS enabled using Let's Encrypt.</p>
<p>Thanks to Fred Posner's <a target="_blank" href="https://www.fredposner.com/1836/kamailio-tls-and-letsencrypt/">article</a> we have understood that there are 2 ways to deal with TLS in Kamailio:</p>
<p><em>quoting Fred Posner</em>:</p>
<blockquote>
<ol>
<li><p>Use a purchased certificate</p>
<ul>
<li><p>Pro: easy to deploy on the client side</p>
</li>
<li><p>Cons: expensive, painful acquisition model</p>
</li>
</ul>
</li>
<li><p>Use a self-signed certificate</p>
<ul>
<li><p>Pro: free</p>
</li>
<li><p>Cons: difficult to deploy on the client side</p>
</li>
</ul>
</li>
</ol>
</blockquote>
<ul>
<li><p>if you use a <strong>self-signed certificate</strong> (not certified by any authority) on your SIP Server, necessarily on the client side you must use its <code>calist.pem</code>; so <em>free but difficult to deploy on the client side</em>.<br />  If you want to go down this road <a target="_blank" href="https://github.com/evoseed/kamailio-tls-letsencrypt/blob/main/doc/SELF-SIGNED-CERT.md">here</a> you can find my guide. You can also find the procedure <a target="_blank" href="https://www.kamailio.org/dokuwiki/doku.php/tls:create-certificates">here</a> and <a target="_blank" href="https://kamailio.org/docs/modules/devel/modules/tls.html">here</a> on <a target="_blank" href="https://kamailio.org">Kamailio</a>'s site):</p>
</li>
<li><p>if you use a <strong>certificate trusted</strong> by a guarantor authority recognized by the client then client-side should not need to load the <code>calist.pem</code>; so <em>easy to deploy on the client side but expensive</em>.<br />  If you want to go down this road you have to buy a certificate and then put it in your Kamailio installation following the same procedure describe for self-signed certificates.</p>
</li>
</ul>
<p>There is, however, an <strong>alternative</strong> that is free, automatable, easy to use and requires no client-side configuration: <code>Let’s Encrypt</code>.</p>
<p>I wrote this article and created this <a target="_blank" href="https://github.com/evoseed/kamailio-tls-letsencrypt">github repo</a> to take a step forward from Fred's excellent article <a target="_blank" href="https://www.fredposner.com/1836/kamailio-tls-and-letsencrypt/">https://www.fredposner.com/1836/kamailio-tls-and-letsencrypt/</a>.<br />Fred explains how to install Let's Encrypt and create a certificate (using <code>letsencrypt-auto</code>, which unfortunately is no longer supported) and how to configure the certificate in kamailio.<br />I want to go one step further and explain how to have a <code>recipe</code> and a ready-to-use <code>docker-compose</code> that allows you to:</p>
<ul>
<li><p>pre-configure the TLS certificate for your domain</p>
</li>
<li><p>pre-configure kamailio to use the certificate</p>
</li>
<li><p>have a container that checks the validity of the certificate and autonomously performs the renewal when necessary</p>
</li>
<li><p>have, ready-to-use, an nginx reverse proxy that uses the certificate: <code>HTTP 80 -&gt; HTTPS</code></p>
</li>
</ul>
<hr />
<h2 id="heading-the-project-structure">The project structure</h2>
<pre><code class="lang-bash">/doc
/modules/db
/modules/kamailio` 
/modules/nginx
env-template
docker-compose.yml
</code></pre>
<hr />
<h3 id="heading-step-to-deploy">Step to deploy</h3>
<ol>
<li><p>clone the repository in your deploy machine <code>git clone https://github.com/evoseed/kamailio-tls-letsencrypt .</code></p>
</li>
<li><p>pre-configure the TLS certificate for our domain</p>
<ul>
<li><p><a target="_blank" href="https://docs.docker.com/compose/install/#install-compose">Install docker-compose</a>.</p>
</li>
<li><p>Modify configuration of nginx<br />  Of course change <code>your.domain.com</code> with you real domain and change <code>1.2.3.4</code> with your real IP address.</p>
<ul>
<li><p><strong>Linux users</strong></p>
<pre><code class="lang-bash">  <span class="hljs-built_in">cd</span> modules/nginx/nginx-certbot
  sed -i <span class="hljs-string">'s/${DOMAIN}/your.domain.com/g'</span> init-letsencrypt.sh
  sed -i <span class="hljs-string">'s/${DOMAIN}/your.domain.com/g'</span> data/nginx/app.conf
  sed -i <span class="hljs-string">'s/${IP}/1.2.3.4/g'</span> data/nginx/app.conf
</code></pre>
</li>
<li><p><strong>MacOS users</strong></p>
<pre><code class="lang-bash">  <span class="hljs-built_in">cd</span> modules/nginx/nginx-certbot
  sed -i <span class="hljs-string">''</span> <span class="hljs-string">'s/${DOMAIN}/your.domain.com/g'</span> init-letsencrypt.sh
  sed -i <span class="hljs-string">''</span> <span class="hljs-string">'s/${DOMAIN}/your.domain.com/g'</span> data/nginx/app.conf
  sed -i <span class="hljs-string">''</span> <span class="hljs-string">'s/${IP}/1.2.3.4/g'</span> data/nginx/app.conf
</code></pre>
</li>
</ul>
</li>
<li><p>Run the init script and follow the Let's encrypt instructions:</p>
<pre><code class="lang-bash">  ./init-letsencrypt.sh
</code></pre>
<p>  <strong>NB</strong> It's quite important to compile correctly the conf in this way; in particular <code>Organization Name</code> and <code>Common Name</code> with your domain</p>
</li>
</ul>
</li>
<li><p>return in the root of the project and compile the <code>.env</code> file following the <code>env-template</code> file</p>
<pre><code class="lang-bash"> <span class="hljs-built_in">cd</span> ../../.. &amp;&amp; cp env-template .env
</code></pre>
<p> and complete the <code>.env</code> file</p>
</li>
<li><p>start all the containers</p>
<pre><code class="lang-bash">  docker-compose up -d
</code></pre>
</li>
</ol>
<hr />
<h3 id="heading-the-running-project">The running project</h3>
<p>When everything has started, what you will see is more or less this:</p>
<pre><code class="lang-bash">CONTAINER ID   IMAGE                    COMMAND                  CREATED       STATUS       PORTS     NAMES
48838aee0057   kamailio-test_kamailio   <span class="hljs-string">"/etc/kamailio/boots…"</span>   2 hours ago   Up 1 hour                kamailio
8103e16bd845   kamailio-test_db         <span class="hljs-string">"docker-entrypoint.s…"</span>   2 hours ago   Up 1 hour                db
e212e6c8241f   certbot/certbot          <span class="hljs-string">"/bin/sh -c 'trap ex…"</span>   2 hours ago   Up 1 hour                certbot
3c101597b160   nginx:1.15-alpine        <span class="hljs-string">"/bin/sh -c 'while :…"</span>   2 hours ago   Up 1 hour                nginx
</code></pre>
<p>The <code>kamailio</code> container, your SIP Server<br />the <code>db</code> container<br />the <code>nginx</code> container as reverse proxy for HTTP to HTTPS and the <code>certbot</code> container who will check every 12 hours whether certificates are still valid or need to be renewed (and will renew them independently if necessary)</p>
<hr />
<h3 id="heading-technical-details">Technical details</h3>
<ol>
<li><p><strong>NB</strong> this project is designed for <strong>dev</strong> purpose, so it is not optimized for production.</p>
<ul>
<li><p><code>docker-compose</code> for example use the build stage</p>
<pre><code class="lang-bash">  ...
  build:
    context: ./modules/db
    dockerfile: Dockerfile
  ...
</code></pre>
<p>  so if you want to have a production ready version you can use built image:</p>
<pre><code class="lang-bash">  ...
  image: your.registry.com/project-name/db:latest
  ...
</code></pre>
</li>
</ul>
</li>
<li><p><strong>NB</strong> this project is designed to run on a VM to which the domain you configured in <code>init-letsencrypt.sh</code> and in the <code>.env</code> points and with a correct domain.</p>
<p> If you run the <code>init-letsencrypt.sh</code> on your local private machine and you set <code>${DOMAIN} = your.domain.com</code> you'll receive an error like this</p>
<pre><code class="lang-bash"> Requesting a certificate <span class="hljs-keyword">for</span> your.domain.com

 Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
 Domain: your.domain.com
 Type:   dns
 Detail: no valid A records found <span class="hljs-keyword">for</span> your.domain.com; no valid AAAA records found <span class="hljs-keyword">for</span> your.domain.com

 Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.

 Some challenges have failed.
 Ask <span class="hljs-keyword">for</span> <span class="hljs-built_in">help</span> or search <span class="hljs-keyword">for</span> solutions at https://community.letsencrypt.org. See the logfile /var/<span class="hljs-built_in">log</span>/letsencrypt/letsencrypt.log or re-run Certbot with -v <span class="hljs-keyword">for</span> more details.
 ERROR: 1
</code></pre>
<p> This happens because Let's Encrypt need to test if you are the admin of the domain.</p>
</li>
<li><p>How is the creation of certificates and their use automated in kamailio?</p>
<p> As you can see in the <code>docker-compose.yaml</code> file, the <code>certbot</code> container and the <code>kamailio</code> container mount both volumes with the same source directory: <code>./module/nginx/nginx-certbot/data/certbot/conf/</code>.<br /> So the <code>certbot</code> create (and renew) the certificates and <code>kamailio</code> use them.</p>
</li>
</ol>
<hr />
<h3 id="heading-thanks-to">Thanks to</h3>
<ul>
<li><p><a target="_blank" href="https://www.fredposner.com">Fred Posner</a> for your <a target="_blank" href="https://www.fredposner.com/1836/kamailio-tls-and-letsencrypt/">article</a></p>
</li>
<li><p><a target="_blank" href="https://www.kamailio.org/w/">Kamailio</a> SIP Server and all your community</p>
</li>
<li><p><a target="_blank" href="https://github.com/wmnnd">Philipp Schmieder</a> for your <a target="_blank" href="https://github.com/wmnnd/nginx-certbot">nginx-certbot</a> repo</p>
</li>
<li><p>my <a target="_blank" href="https://evoseed.io">evoseed</a> team</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[VoIP: fundamentals of SIP and related topics  - part #6: audio problems and the quality of a VoIP call]]></title><description><![CDATA[In the previous episode I talked about the main tools for working with VoIP.
https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip
In this episode, I'll continue on this trend, tal...]]></description><link>https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-6-audio-problems-and-the-quality-of-a-voip-call</link><guid isPermaLink="true">https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-6-audio-problems-and-the-quality-of-a-voip-call</guid><category><![CDATA[Voice]]></category><category><![CDATA[tips]]></category><category><![CDATA[communication]]></category><category><![CDATA[tools]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Sun, 09 May 2021 16:01:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620469560618/MV0ogVfeJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the previous episode I talked about <em>the main tools for working with VoIP.</em></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip">https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip</a></div>
<p>In this episode, I'll continue on this trend, talking about the <strong>audio problems and  quality of communication</strong>.</p>
<hr />
<p>Good customer service includes <strong>quality control</strong> with <em>proactive monitoring</em> and <strong>feedback analysis</strong> for continuous improvement.<br />Proactive monitoring can be somewhat expensive (but we will see that it does not necessarily have to), but it is definitely a long-term investment.<br />In your opinion is it better to save on proactive monitoring and quality systems and that your customer reports anomalies and poor quality of calls, or is it better that you monitor the quality of services and that you proactively contact the customer (before do him) in case of anomalies?  </p>
<blockquote>
<p>I am talking about combining the more classic <em>QoS</em> with <em>QoE</em>.</p>
</blockquote>
<hr />
<p>In this article I will talk about:</p>
<ul>
<li>which are the parameters to be taken into account to evaluate an <strong>audio problems</strong></li>
<li>which are the parameters to be taken into account to evaluate the <strong>goodness of a call</strong></li>
<li>how to <strong>monitor</strong> these values</li>
</ul>
<hr />
<h2 id="audio-problems">Audio problems</h2>
<p>The main audio problems are related to:</p>
<ul>
<li><em>internet connection problems</em>: if your internet connection is poor, or is not dedicated to VoIP audio, you can run into the following problems<ul>
<li><strong>Packet loss</strong>: the packet loss in a VoIP call is recognizable by a <em>robotic or synthetic voice and gaps</em></li>
<li><strong>Jitter</strong>: jitter is the divergence of an expected voice packet from its presumed arrival time. For instance, two packets may arrive at the same time, or out of order due to network congestion. These problems can cause audio quality to drop. A jitter buffer then is an intermediary queue that’s used to order packets according to their expected timing values in an attempt to minimize jitter. Using a jitter buffer can potentially improve call quality. The Jitter in a VoIP call is recognizable by a <em>distorted voice</em></li>
<li><strong>Latency</strong>: The high latency in a real-time communication risks making the service unusable. The Latency in a VoIP call is recognizable by a <em>collisions when people start to talk at the same time</em></li>
</ul>
</li>
</ul>
<p>The tools mentioned in the  <a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip">previous article</a>  can help you find out if the call was affected by these network problems.</p>
<ul>
<li>other strange audio problems<ul>
<li><strong>echo</strong>: echo problems follow 3 main rules  <ul>
<li>is always generated in the opposite side of who is hearing the echo  </li>
<li>is frequently caused by the PSTN, use and echo canceller  </li>
<li>turn-off the speaker phone and use the handset to test  </li>
</ul>
</li>
</ul>
</li>
</ul>
<p>There's an old but interesting CISCO guide titled "<em>Recognizing and Categorizing Symptoms of Voice Quality Problems</em>", that I found thanks to <a target="_blank" href="https://www.linkedin.com/in/flavioegoncalves/">Flavio E. Goncalves</a>,  which can be useful for categorizing the audio problem you are having.<br />You can find it here:  <a target="_blank" href="https://www.cisco.com/c/en/us/support/docs/voice/voice-quality/30141-symptoms.html">https://www.cisco.com/c/en/us/support/docs/voice/voice-quality/30141-symptoms.html</a>  </p>
<p>A fundamental metric to analyze the goodness of a VoIP call is the <strong>MOS</strong> (Mean Opinion Score).<br />MOS is terminology for audio, video and audiovisual quality expressions as per ITU-T P.800.1. It refers to listening, talking or conversational quality, whether they originate from subjective or objective models.</p>
<pre><code><span class="hljs-attribute">Very</span> Good: <span class="hljs-number">4</span>.<span class="hljs-number">3</span>-<span class="hljs-number">5</span>.<span class="hljs-number">0</span>
<span class="hljs-attribute">Bad</span>: <span class="hljs-number">3</span>.<span class="hljs-number">1</span>-<span class="hljs-number">3</span>.<span class="hljs-number">6</span>
<span class="hljs-attribute">Not</span> Recommenced : <span class="hljs-number">2</span>.<span class="hljs-number">6</span>-<span class="hljs-number">3</span>.<span class="hljs-number">1</span>
<span class="hljs-attribute">Very</span> Bad: <span class="hljs-number">1</span>.<span class="hljs-number">0</span>-<span class="hljs-number">2</span>.<span class="hljs-number">6</span>
</code></pre><p>Calculating the MOS of each call could be challenging; fortunately the <strong>RTCP</strong> protocol comes to our aid: RTCP is a protocol that collects statistics on the quality of service of the RTP protocol and carries information about the participants in a session.  </p>
<p>Each VoIP call then uses the SIP to "organize and manage" the call, the RTP to manage the exchange of audio and the RTCP to monitor its quality.</p>
<p>Homer (just to name one at random :) ) makes our life even easier as it traces the RTCP data into a very comfortable graphic format like this</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620575238590/zjBM6ya3G.png" alt="Schermata 2021-05-09 alle 17.46.05.png" /></p>
<hr />
<h2 id="quality-of-a-call-the-journey-to-qoe">Quality of a call: the journey to QoE</h2>
<p>The quality, in a broad sense, of a call is not only given by the goodness of the audio stream.<br />There are other parameters that those who do business with VoIP traffic must take into consideration.<br />The ACD and ASR parameter are the most commonly used metrics to indicate VoIP route quality, but there are also other interesting ones:</p>
<ul>
<li><strong>ACD</strong> (Average call duration): It is the average length of an answered call made over the network:<br /><code>ACD = duration of all answered calls / number of answered calls</code><br />For example, if there were 62 answered calls with a total duration of 145 minutes, then:<br /><code>ACD = 145 [duration of all answered calls] / 62 [total number of answered calls] = 2.34 minutes</code><br /><strong>An ACD of 4–5 minutes is considered okay, whereas anything above 6 minutes is excellent.</strong></li>
<li><strong>ASR</strong> (Answer-Seizure Ratio): ASR is the percentage of the number of successfully connected calls to the number of attempted calls (it is also called the call completion rate):<br /><code>ASR % = (total number of answered calls / total number of calls) × 100</code><br />For example, if there were 156 calls dialed of which 62 were successfully connected, then:<br /><code>ASR (%) = (62 [successful calls] / 156 [dialed calls]) x 100 = 39.74%</code><br /><strong>ASR should be at least 40–50%, and anything above 60% would indicate an excellent quality service.</strong></li>
<li><strong>NER</strong> (Network Effectiveness Ratio): NER measures the ability of a network to deliver a call to the called terminal. Busy signals and other call failure due to user behaviour are counted as "successful call delivery" for NER calculation purposes. Unlike ASR, NER excludes the effects of customer and terminal behaviour. 
<code>NER(%) = ((answered calls + user busy + ring no answer + terminal reject)/(total number of calls)) x 100</code></li>
<li><strong>PDD</strong> (Post-Dial Delay) Post-dial delay is the measurement of how long it takes for a calling party to hear a ringback tone after initiating a call. Technically it is the delta between the SIP INVITE and a 180 Ringing or 183 Session Progress response. High PDD values are the main reasons for the low ASR. People don’t want to wait too long before hearing the ringtone, and they close the phone when it’s not connected. This will cause to miss calls. When the caller closes, call ends and there will be no re-route. </li>
</ul>
<hr />
<h2 id="how-to-monitor-the-call-quality">How to monitor the call quality</h2>
<p>Also in this article I will again mention the  <a target="_blank" href="https://sipcapture.org/">Sipcapture</a> team and and their valuable work done in the latest versions of  <a target="_blank" href="https://github.com/sipcapture/homer">Homer</a>; they integrated Grafana, creating default dashboards that track a lot of very interesting data, for example the datas from RTCP</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620570917726/5HGzi6LlQ.png" alt="Schermata 2021-05-09 alle 16.33.46.png" /><br />You can also find the Homer's Grafana dashboard here:  <a target="_blank" href="https://grafana.com/grafana/dashboards/11764">https://grafana.com/grafana/dashboards/11764</a> </p>
<p>In my experience, I have combined the use of <strong>Homer</strong> with a double control based on <strong>zabbix&amp;grafana</strong>.<br />I use <strong>Homer's Grafana</strong> dashboards to monitor the general trend of the call flow passing through our SIP servers, while I use a specific data collection via <strong>Zabbix&amp;Grafana</strong> to track and graph the specific data of the call quality and quantity with the carriers; I need this to keep constantly monitored our suppliers.<br />This is an example of one of our Grafana boards to track the quality of the service provided to us by suppliers in real time</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620571574310/yGg9bdgG-.png" alt="grafana.png" /></p>
<p>The use of tools like grafana are also powerfull to predict the trend of the use of your resources.</p>
<hr />
<blockquote>
<p>So my advice at the end of this article as <em>Hans Rosling</em> says in his book <strong>Factfulness</strong> is: <strong>rely on the data, they are the only antidote to the cliché</strong></p>
</blockquote>
<hr />
<p>That’s all for this episode too. Let me know what you think about it.</p>
<p>Thanks a lot for reading, sharing and comment this article.</p>
<p>Thanks to  <a target="_blank" href="undraw.co">undraw.co</a>  for the beautiful illustration I used in the header</p>
<p>Cheers!</p>
<p><em>To be continued …</em></p>
]]></content:encoded></item><item><title><![CDATA[VoIP: fundamentals of SIP and related topics  - part #5: the main tools for working with VoIP]]></title><description><![CDATA[Here we are, close to the end of this mini-series.In the previous episode I talked about the UA PBX, standard configurations and some security tips.  
https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-4-ua-pbx-stand...]]></description><link>https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip</link><guid isPermaLink="true">https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip</guid><category><![CDATA[Voice]]></category><category><![CDATA[problem solving skills]]></category><category><![CDATA[Computer Science]]></category><category><![CDATA[communication]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Sun, 02 May 2021 11:40:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619942473728/CFAA5mGBW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here we are, close to the end of this mini-series.<br />In the previous episode I talked about the <em>UA PBX, standard configurations and some security tips</em>.  </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-4-ua-pbx-standard-configurations-and-some-security-tips">https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-4-ua-pbx-standard-configurations-and-some-security-tips</a></div>
<p>In this episode I'll talk about the <strong>main tools</strong> to analyze VoIP issues:  </p>
<ul>
<li>whireshark / tshark</li>
<li>sngrep</li>
<li>homer</li>
</ul>
<hr />
<h1 id="whireshark-tshark">Whireshark / tshark</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619941957000/7d_D8aPDN.png" alt="image.png" /></p>
<p>Quoting from the  <a target="_blank" href="https://www.wireshark.org/">official website</a> :</p>
<blockquote>
<p>Wireshark is the world’s foremost and widely-used network protocol analyzer. It lets you see what’s happening on your network at a microscopic level and is the de facto (and often de jure) standard across many commercial and non-profit enterprises, government agencies, and educational institutions. Wireshark development thrives thanks to the volunteer contributions of networking experts around the globe and is the continuation of a project started by Gerald Combs in 1998.</p>
</blockquote>
<p>On the official website and in general on the internet you will find many tutorials to work to the maximum potential with this special tool.</p>
<p>I will now give you some quick examples (with some screenshots) of using this tool:</p>
<ol>
<li><p>open the whireshark program and choose, in the main screen, which interface you want to analyze. I choose my wifi interface
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619943156932/mB42qa_gv.png" alt="Screenshot from 2021-05-02 10-11-57.png" /></p>
</li>
<li><p>Now you'll start to see the flow of all the packages flowing through your interface. We set the filter suitable for our purpose: we choose to monitor only <strong>SIP</strong> packets. It's very easy, just go to the "Apply a display filter" bar and type SIP
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619943503834/07hDv1jKB.png" alt="Screenshot from 2021-05-02 10-18-11.png" /></p>
</li>
<li><p>now let's try to make a SIP call from our client and see what happens in whireshark.<br />And voilà, here are all the SIP packets of the call.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619944183755/Xo6-GXkxL.png" alt="capture.png" />
You can double-click on every package to enter in detail mode and see all the details of the layers of the particular packet
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619944760531/ZF255Mbg6.png" alt="Screenshot from 2021-05-02 10-35-26.png" /></p>
</li>
</ol>
<p>There is an interest section for the VoIP troubleshooting, the <strong>Telephony</strong> menu; here you can find:</p>
<ul>
<li>the <strong>VoIP Calls</strong> menu 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619946869347/Eqq8bZrPZ.png" alt="Screenshot from 2021-05-02 11-11-43.png" />
with the <code>Flow sequence</code> view
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619946878269/916teZ-I_.png" alt="Screenshot from 2021-05-02 11-11-59.png" /></li>
<li>the <strong>RTP/RTSP</strong> menu, to analize the MOS and quality of stream<br />and so on.</li>
</ul>
<p>The (very small) <em>limitation</em> of this tool is that if I have to do a realtime analysis on a remote server (which has no graphical environment), I will first have to make a capture with <strong>tshark</strong>, download the pcap file on my PC and then open the file with wireshark to analyze it thoroughly</p>
<p><a target="_blank" href="https://www.wireshark.org/docs/man-pages/tshark.html">Tshark</a>  is a network protocol analyzer as wireshark. Is more or less the same tool, but it has no GUI, you drive it from the <strong>shell</strong>. It is therefore very convenient for servers that do not have a graphical environment.<br />As you can see the result of capture is the same, but in shell
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619945696126/iiIzS496l.png" alt="Screenshot from 2021-05-02 10-46-02.png" />
An interest option of tshark is <code>-w</code></p>
<blockquote>
<p>If the -w option is specified when capturing packets or reading from a capture file, TShark does not display packets on the standard output. Instead, it writes the packets to a capture file with the name specified by the -w option.  </p>
</blockquote>
<p>So the typical use I make of the <strong>tshark + wireshark combo</strong> is: </p>
<ul>
<li>I launch <strong>tshark</strong> with <code>-w</code> on the remote server where I have to troubleshoot</li>
<li>when I have captured what I need I interrupt tshark</li>
<li>I download the pcap locally </li>
<li>and at this point I open the <strong>pcap</strong> file with <strong>whireshark</strong> and proceed to an in-depth analysis of the problem</li>
</ul>
<hr />
<h1 id="sngrep">Sngrep</h1>
<blockquote>
<p>sngrep is a useful tool for displaying SIP call message flows.  It supports live capture to display realtime SIP packets and can also be used as PCAP viewer.  sngrep supports UDP, TCP and TLS.</p>
</blockquote>
<p>I don't dwell on how to install the tool, there is a lot of material on the net; here are some links:</p>
<ul>
<li>https://support.simwood.com/hc/en-us/articles/223811708-Packet-Capturing-sngrep</li>
<li>http://sipxcom.org/get-to-know-sngrep/</li>
</ul>
<p>It is very useful when you need to make realtime captures on servers without a graphical environment. <strong>Sngrep</strong> graphics are very intuitive, its strength is to show the flow of SIP messages in visual form.</p>
<p>When you run sngrep, you star to see the list of calls</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619952928581/nzZrVC7k-.png" alt="image.png" /></p>
<p>Then you can decide to enter in the details of a specific call to see all the packets
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619953025799/leRrYr2qx.png" alt="image.png" /></p>
<p>With <strong>sngrep</strong> you can also filter and save in <em>pcap</em> format (so it could be an alternative to <em>tshark</em> to capture calls and then analyze in depth with <em>wireshark</em>)</p>
<p><em>Thanks to  <a target="_blank" href="https://support.simwood.com/hc/en-us/articles/223811708-Packet-Capturing-sngrep">Alex Lane</a>  for the images</em></p>
<hr />
<h1 id="homer">Homer</h1>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619953885344/QKbgWTaXV.png" alt="image.png" /></p>
<p><code>Homer</code> from  <a target="_blank" href="http://sipcapture.org/">Sipcapture</a> is a magnificent tool that <code>Change the way you Analyze RTC and Debug VoIP Services</code>.</p>
<blockquote>
<p>HOMER is part of the SIPCAPTURE stack: A robust, carrier-grade and modular VoIP and RTC Capture Framework for Analysis and Monitoring with native support for all major OSS Voice platforms and vendor-agnostic Capture agents.</p>
</blockquote>
<p>With <code>Homer</code> there is no need to activate a capture in realtime as much as your client has a problem, with <code>Homer</code> you have all the call flows ready to use and accessible from a very usable dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619954195490/tft_CdaB1.gif" alt="sipcapture_gif.gif" /></p>
<p>The <code>Homer</code> ecosystem is composed, simplistically speaking, of a <strong>capture server</strong> and a <strong>capture agent</strong>.<br />The <strong>agent</strong> runs on your VoIP network, captures packets and sends them to the <strong>server</strong>. The server stores them and makes them usable.  </p>
<p>On  <a target="_blank" href="http://sipcapture.org/#home">sipcapture website</a>  you will find a lot of more precise details.</p>
<hr />
<p>I want to conclude with a thought that I have accrued in my experience as a problem solver:</p>
<ul>
<li><p><strong>never skip any of the 4 phases</strong>:</p>
<ol>
<li><p><code>symptom collection</code>: interview the customer who reports the problem to you with <strong>targeted questions</strong>; collect the symptoms and discard the hypotheses of diagnosis that the client brings you.<br />When a sick person goes to the doctor, the doctor holds the parts like "<em>I have acute pain here. I ate this yesterday. Every time I do this movement I feel sick. It had already happened to me</em>", and discards phrases like "<em>I think I have indigestion </em>".<br /><strong>The diagnosis is up to you and not by your client</strong>.</p>
</li>
<li><p><code>anamnesis</code>: after the client has explained the symptoms to you, collect all the important information that can help you with the diagnosis that you will have to make in the next phase; <strong>try to reduce the variables</strong></p>
</li>
<li><p><code>diagnosis / analysis</code>: with the list of symptoms and anamnesis combined with your experience, <strong>do the magic!</strong></p>
</li>
<li><p><code>resolution</code>: implement the solution to solve the problem that the customer has reported to you. Then call your customer and explain to him, without all the details but with an exhaustive description, what you encountered and how you solved him.  </p>
</li>
</ol>
</li>
<li><p>when you approach a problem, do not discard the simplest reasons in favor of abstruse hypotheses, on the contrary, <strong>start from the simplest hypotheses</strong>.
Usually when we open the problem that a customer reports to us, we immediately start off on the tangent and begin to hypothesize astral conjunctions, abstruse bugs or crazy hackers .. and then most of the time the problem is that the power plug is unplugged.</p>
</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://media.giphy.com/media/9PTaAhwri56V2/giphy.gif">https://media.giphy.com/media/9PTaAhwri56V2/giphy.gif</a></div>
<hr />
<p>That’s all for this episode too. Let me know what you think about it.</p>
<p>Thanks a lot for reading, sharing and comment this article.</p>
<p><em>Thanks to  <a target="_blank" href="http://undraw.co">undraw.co</a>  for the beautiful illustration I used in the header</em></p>
<p>Cheers!<br />We are quite close to the end of this mini-series, but I've some other surprise<br /> <a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-6-audio-problems-and-the-quality-of-a-voip-call">To be continued …</a> </p>
]]></content:encoded></item><item><title><![CDATA[VoIP: fundamentals of SIP and related topics - part #4: UA PBX, standard configurations and some security tips]]></title><description><![CDATA[Here we are with the fourth appointment with the mini-series about VoIP.You can find the last episode here:
https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-3-sdp-and-rtp
In this episode I'll quickly talk about the...]]></description><link>https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-4-ua-pbx-standard-configurations-and-some-security-tips</link><guid isPermaLink="true">https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-4-ua-pbx-standard-configurations-and-some-security-tips</guid><category><![CDATA[Voice]]></category><category><![CDATA[communication]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Sun, 25 Apr 2021 14:59:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619359297587/e3i7975Fj.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here we are with the <strong>fourth</strong> appointment with the mini-series about VoIP.<br />You can find the <strong>last episode</strong> here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-3-sdp-and-rtp">https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-3-sdp-and-rtp</a></div>
<p>In this episode I'll quickly talk about the most common configurations of the PBX, including its security.</p>
<blockquote>
<p>A SIP <em>user agent</em> (<strong>UA</strong>) is a logical network end-point used to create or receive SIP messages and thereby manage a SIP session.<br />A SIP UA can perform the role of a <em>User Agent Client</em> (<strong>UAC</strong>), which <em>sends SIP requests</em>, and the <em>User Agent Server</em> (<strong>UAS</strong>), which <em>receives the requests</em> and returns a SIP response. 
 These roles of UAC and UAS only last for the duration of a SIP transaction.</p>
</blockquote>
<hr />
<p>The most common configurations for a PBX used to make and receive VoIP calls are as follows:</p>
<ul>
<li><p><strong>PBX with public interface</strong>: in this case, the PBX will usually have two network interfaces, a <strong>private</strong> one to communicate with the phones in the LAN, and a <strong>public</strong> one to communicate with the provider from which it purchases the VoIP numbers.<br />In this configuration, the system administrator who manages the PBX will have to pay close attention to its security as it is exposed to attacks from the public network; however, problems related to the presence of private IPs in SIP packets or in the SDP will be rare (if in the SIP packets sent to the provider that provides the VoIP account, there are private IPs, you could run into calls with one-way audio or that do not take place).</p>
</li>
<li><p><strong>PBX with private interface behind NAT</strong>: in this case, the PBX has only 1 network interface with <strong>private IP</strong>. It is behind the management of a router that will populate the NAT tables and route the packets to and from the PBX.<br />This type of configuration could be more secure but can generate <strong>NAT traversal problems</strong>. The problems of this type are due to the fact that the PBX having only a private interface, if not well configured, could forge its packets with private IP; the SIP proxy that will receive an INVITE with <code>Via</code>, <code>Contact</code>, and <code>SDP</code> with <strong>private IP</strong>, will have serious difficulties in managing the call in the best possible way.<br />Some routers implement <strong>SIP ALG mechanisms</strong> to parse and rewrite SIP packet headers where necessary; however, these mechanisms usually do not work correctly and therefore it is preferable to disable them.<br />Usually SIP proxies implement <strong>NAT HELPER mechanisms</strong>, which by comparing the IP of origin of the SIP packet with the IPs contained in its headers will understand if the UA that generated the request is behind NAT or not; if it understands that the PBX is behind NAT, it will attempt to correct the private IPs present in the headers.<br /><a target="_blank" href="https://www.kamailio.org/w/">Kamailio</a> , a beautiful Open Source SIP Server, for example, has an entire module dedicated to the  <a target="_blank" href="https://www.kamailio.org/docs/modules/stable/modules/nathelper.html">nathelper</a> , with functions such as  <a target="_blank" href="https://www.kamailio.org/docs/modules/stable/modules/nathelper.html#nathelper.f.fix_nated_contact">fix_nated_contact()</a> that rewrites the "Contact" header.</p>
</li>
</ul>
<p>Some PBXs (for example Asterisk) implement configurations and mechanisms for proper management behind NAT:</p>
<ol>
<li>the <strong>externip</strong> (<em>external host</em>) parameter, to be added to the asterisk <strong>sip.conf</strong> indicates the IP that will be used as the source for all SIP messages when the PBX is behind NAT; configuring this parameter will allow asterisk to forge SIP packets correctly.</li>
<li>Another tipical mechanisms is the <strong>STUN</strong> (<em>Simple Traversal of UDP through NAT</em>). STUN is an industry standard approach for traversal of NAT and the technical details are published as RFC 3489.<br />This mechanism relies on an external server (STUN server); the PBX, when it has to forge a SIP packet, will contact the STUN server; the STUN server will ask: Is the PBX behind a NAT device? What is the external IP address of the NAT device? It will then find the answers, and the external IP address of the PBX will be returned to the PBX; the PBX can then use it to correctly forge its SIP packets.</li>
</ol>
<hr />
<p>Nowadays any service exposed on the internet is subject to attacks by malicious users. If you have a PBX (at home or in the cloud), the illegitimate users and bots will repeatedly attempt to break into yours system trying to authenticate with different credentials.</p>
<h2 id="security-tips">Security tips:</h2>
<ol>
<li>The first thing to do to secure the PBX is to <strong>configure a
firewall</strong> to protect it, inhibiting access to:<ul>
<li>all unnecessary ports (DENY by default)</li>
<li>all unnecessary source IP addresses (put only the
IP from which your customer will have to access the switchboard).</li>
</ul>
</li>
<li><strong>Apply restrictions at the source IP level</strong><br />If you know where the packets will come from (VoIP operator, phones that connect from the outside) enables access only to IP addresses known.<br />If, on the other hand, you do not have the possibility to know in advance the IP addresses source or ranges, use the GEOIP functionality to limit access to "your county" / European IPs only.</li>
<li><strong>Protect yourself with strong passwords</strong><br />Use strong passwords (letters + numbers + special characters) of at least 12 characters for both SIP users and HTTP users (if access the WEB panel they can do what they want).</li>
<li><strong>International calls</strong><br />If you don't need it, block your PBX from being able to do so calls to international numbers and / or extra-cost numbers.<br />A possible alternative, if provided by the switchboard, is that of enable international calls by entering a PIN code.</li>
<li><strong>Anti-fraud</strong>
An additional level of security is to be able to "close the gate when some oxen have escaped ". In this sense, use a VoIP provider which has automatic management within its system anti-fraud allows you to limit the damage; the system will block calls outgoing (or only international ones) when the consumption threshold will be been exceeded.</li>
<li><strong>Use Fail2Ban (if you PBX is a linux based machine)</strong><br />Fail2ban is a security tool written in Python. It is meant for prevent brute force attacks.
Scan log files and block IP addresses that have too many password failures or use of exploits. (source Wikipedia)
It is able to read system and PBX service log files and blacklist IP addresses responsible for login attempts repeated.</li>
</ol>
<hr />
<p>Here a complete representation of a VoIP call from caller to callee</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619362246448/Mhrsp-hIy.png" alt="SIP_basic-call&amp;concepts-CALL.png" /></p>
<hr />
<p>That’s all for this episode too.
Let me know what you think about it.</p>
<p>Thanks a lot for reading, sharing and comment this article.</p>
<p><em>Thanks to  <a target="_blank" href="http://undraw.co">undraw.co</a></em> for the beautiful illustration I used in the header  </p>
<p>Cheers!
To be continued in "<em> <a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip">part #5: the main tools for working with VoIP</a> </em>" …</p>
]]></content:encoded></item><item><title><![CDATA[VoIP: fundamentals of SIP and related topics - part #3: SDP & RTP]]></title><description><![CDATA[New week and new episode, the fourth appointment with the mini-series about VoIP.You can find the last here:
https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-2-the-basic-sip-headers

In this episode I’ll talk about...]]></description><link>https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-3-sdp-and-rtp</link><guid isPermaLink="true">https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-3-sdp-and-rtp</guid><category><![CDATA[Voice]]></category><category><![CDATA[communication]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Sat, 17 Apr 2021 22:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619357907624/h9w4dloFW.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>New week and new episode, the fourth appointment with the mini-series about <strong>VoIP</strong>.<br />You can find the last here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-2-the-basic-sip-headers">https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-2-the-basic-sip-headers</a></div>
<hr />
<p>In this episode I’ll talk about the <strong>SDP &amp; RTP</strong>:</p>
<ol>
<li>What is <strong>SDP</strong></li>
<li><strong>Codec</strong></li>
<li>What is <strong>RTP</strong></li>
</ol>
<hr />
<p>As I mentioned in the previous articles, <strong>SIP</strong> is only one of the protocol engaged in a VoIP call.<br />The <strong>SIP</strong> is the protocol that deals with the exchange of messages (on UDP or TCP) to <em>establish</em>, <em>modify</em> and <em>terminate</em> a session. However, it does not deal with the exchange of the audio stream.</p>
<p>The management and exchange of the audio stream is delegated to 2 other protocols: the <strong>SDP</strong> and the <strong>RTP</strong>.</p>
<hr />
<h2 id="heading-what-is-sdp">What is SDP</h2>
<p>The <strong>SDP</strong> protocol is used to describe the details of the multimedia session.<br />The details of the session can be found in the body of some SIP messages (such as the <code>INVITE</code> or <code>200 OK</code>).</p>
<p>This is a screenshot of an INVITE take with <strong>Wireshark</strong> (one of the useful tools for debugging the SIP; we will see in detail in one of the next episodes)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619358150088/lZ98cABTx.png" alt="wireshark.png" /></p>
<p>As you can see, the SIP, as we already know, it’s composed of: <strong>Request-Line</strong>, <strong>Message Header</strong> (I talked about the most important headers in the last episode) and <strong>Message Body</strong>.</p>
<p>Let’s expand the package:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619358205833/Z_QcPUu5t.png" alt="wireshark-expand.png" /></p>
<p>The <strong>Request-Line</strong> (yellow) is composed by the <strong>Method</strong> and the <strong>Request-URI</strong> (the destination of the packet).<br />The <strong>Message Header</strong> (green) is made up of all the headers we talked about last episode.<br />And the <strong>Message body</strong> (blue) contains the <strong>SDP</strong> informations.</p>
<p>The most important <strong>SDP</strong> informations to know are the <strong>c</strong> and the <strong>m</strong> lines.
In the <strong>Connection Data</strong>, the <strong>c field</strong> there is the <strong>IP address</strong> at which you want to receive the multimedia stream.<br />The <strong>Media Descriptions</strong>, the <strong>m</strong> field describes the port at which the stream is to be received and its encoding (the codecs you are allowed to use).</p>
<blockquote>
<p>If you are talking to a SIP switch on the public network and in the c field you put your private IP (instead of your public IP), the call may have one-way audio, because the SIP exchange you want to contact will not know which is your public IP where to send the audio stream; so they will hear you but you don’t hear them.</p>
</blockquote>
<hr />
<h2 id="heading-codec">Codec</h2>
<p>Codecs are comparable to languages known to humans. If you have to talk to a person, you have to use a common language, otherwise you will not understand each other. If your mother tongue is different, before starting to converse, you will agree on which language to speak.<br />It could happen that you say: "<em>I know English, French and Spanish and you?</em>", and your interlocutor replies: "<em>I know Russian, Slovenian and English, so let’s speak in English</em>".<br />The only language common to you two is <em>English</em> and therefore your communication will take place in <em>English</em>.<br />This is the mechanism that underlies the management of <strong>codecs</strong> in a VoIP communication.</p>
<p>Caller and callee declare in the SDP the supported codecs in order of preference.<br />In the presence of several common codecs between the caller and the callee, the first codec chosen by the callee is generally used.<br />In any case it is possible to have media streams with any of the supported codecs and they can change during the phone call.<br />To undo the declaration of support for a given codec (or to declare that a new one is supported) you need to send a new INVITE (RE-INVITE) with a new SDP.</p>
<p>It could happen that the two interlocutors do not have a language, a codec in common; in this case the communication cannot be established, unless there is a B2BUA in the communication that offers the <strong>Transcoding</strong> service, i.e. it will act as <strong>simultaneous translator</strong>.</p>
<p>Each codec has a numeric code and a name that identifies it.<br />The most used voice codecs in Europe are:<br /><code>8 pcma</code> (or g711-alaw)<br /><code>18 g 729</code><br /><code>9 g722</code><br /><code>3 gsm</code><br /><code>0 pcmu</code> (or g711-ulaw)<br /><code>13 comfort noise</code><br /><code>101 telephone event</code>  </p>
<p>In the example above, you can see that the caller proposed the following codecs: <code>8, 0, 101</code> (Look in the Media Description <strong>m</strong> line).</p>
<hr />
<h2 id="heading-what-is-rtp">What is RTP</h2>
<p>The <strong>RTP</strong> (<strong>Real-time Transport</strong>) application protocol takes care of sending a media stream to the endpoint.<br />The only transport protocol used is <strong>UDP</strong>.<br />The port to which the stream is to be received is communicated in the SDP, in the field <strong>m</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619358571196/IbGIiksHu.png" alt="sngrep-rtp.png" /></p>
<p>In this image, taken with another tool (<strong>sngrep</strong>) that we will see in the next episode, you can see the SIP packets (red and green) and the RTP stream (white).</p>
<hr />
<p>That’s all for this episode too.<br />Let me know what you think about it.</p>
<p>Thanks a lot for reading, sharing and comment this article.  </p>
<p><em>Thanks to  <a target="_blank" href="http://undraw.co">undraw.co</a></em> for the beautiful illustration I used in the header  </p>
<p>Cheers!<br />To be continued in " <a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-4-ua-pbx-standard-configurations-and-some-security-tips">part #4: UA PBX, standard configurations</a> " …</p>
]]></content:encoded></item><item><title><![CDATA[VoIP: fundamentals of SIP and related topics - part #2: the basic SIP headers]]></title><description><![CDATA[Here we are with the third appointment with the mini-series about VoIP.You can find the last here:
https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-1-basic-concepts-of-sip

In this episode I’ll talk about the basic...]]></description><link>https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-2-the-basic-sip-headers</link><guid isPermaLink="true">https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-2-the-basic-sip-headers</guid><category><![CDATA[Voice]]></category><category><![CDATA[communication]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Sun, 11 Apr 2021 13:32:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619356769208/BxK21QlTJ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here we are with the <strong>third</strong> appointment with the mini-series about VoIP.<br />You can find the <strong>last</strong> here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-1-basic-concepts-of-sip">https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-1-basic-concepts-of-sip</a></div>
<hr />
<p>In this episode I’ll talk about the <strong>basic SIP headers</strong>:</p>
<ol>
<li>Request-URI</li>
<li>From &amp; To</li>
<li>Call-ID</li>
<li>Via &amp; Contact</li>
<li>Record-route &amp; Route</li>
<li>P-Asserted-Identity Remote-Party-ID e P-Preferred-Identity</li>
</ol>
<hr />
<h2 id="request-uri">Request-URI</h2>
<p>The <strong>Request-URI</strong> indicates the URI (the address) of the UAS to which the packet is to be sent.</p>
<p>The initial <strong>Request-URI</strong> (of an INVITE not in dialog) must be equal to the URI present in the To field (except for REGISTERS).</p>
<p>How to write a R-URI? The <strong>Request-URI</strong> of requests in dialog must follow this rule:</p>
<ul>
<li>if <strong>there are NO</strong> <em>Record-Route</em> header, the <strong>Request-URI</strong> must be equal to the URI present in the <strong>Contact</strong> of the response.</li>
<li>if <strong>there are</strong> <em>Record-Route</em> headers:<ol>
<li>if the first URI of the Record-Route headers contains the parameter <strong>lr</strong>, then the UAC must use the <strong>Contact</strong> of the response to populate the Request-URI (plus it must add the routes)</li>
<li>if the first URI of the Record-Route headers does NOT contain the <strong>lr</strong> parameter, then the UAC must use the first Record-Route header of the response to populate the Request-URI</li>
</ol>
</li>
</ul>
<hr />
<h2 id="from-and-to">From &amp; To</h2>
<p>The <strong>From</strong></p>
<pre><code><span class="hljs-attribute">From</span>: “<span class="hljs-number">0123456</span>” &lt;sip: <span class="hljs-number">0123456</span>@<span class="hljs-number">192.0.2.123</span>&gt;; tag = <span class="hljs-number">1234</span>
</code></pre><p>This header indicates the logical entity from which the request originates; usually it is the AOR (address-of-record) of the user.<br />It contains a SIP or SIPS URI and can contain the display name (“0123456” in our example).
This field is used by the SIP proxy that receives the request, to determine which “processing rule” to apply to this request (for example, that user may not be enabled for calls).</p>
<p>The <strong>To</strong></p>
<pre><code><span class="hljs-attribute">To</span>: “<span class="hljs-number">0123456</span>” &lt;sip: <span class="hljs-number">0123456</span>@<span class="hljs-number">192.0.2.124</span>&gt;; tag = <span class="hljs-number">1234</span>
</code></pre><p>This header indicates the logical entity you want to contact, the AOR of the target user of the request.<br />It contains a SIP or SIPS URI and can contain the display name (“0123456” in our example).</p>
<hr />
<h2 id="call-id">Call-ID</h2>
<pre><code><span class="hljs-attribute">Call-ID</span>: f88f9s8f8fsd898332-fff23fsf-<span class="hljs-number">23</span><span class="hljs-variable">@192</span>.<span class="hljs-number">0.2</span>.<span class="hljs-number">234</span>
</code></pre><p>It is used as a globally unique identifier to group a series of SIP messages.<br />In all requests and responses exchanged by UA in the same dialog, <strong>it must always be the same</strong>.
It should be the same in all registration requests from a UA.
Combined with the from-tag and the to-tag, it uniquely identify a dialog.</p>
<hr />
<h2 id="via-and-contact">Via &amp; Contact</h2>
<p>The <strong>Via</strong> (present in a request) identifies the address at which the person who generated the packet expects to receive the response.<br />The Contact contains a SIP or SIPS URI and represents a direct way to contact whoever generated the packet.</p>
<blockquote>
<p>So the Via says where to send the answers; the contact instead indicates where to send future requests in the same dialog.<br />To find out where to send a 200OK (which is a response) I will use the address present in the Via, while to send a BYE (which is a request) I will use the address present in the Contact.</p>
</blockquote>
<p>Via works with the <strong>breadcrumbs mechanism</strong>: a new Via is added to the head from each SIP element that packet passes through and the previous hops are left.</p>
<hr />
<h2 id="record-route-and-route">Record-route &amp; Route</h2>
<p>Only proxies that use the <strong> <a target="_blank" href="https://www.rfc-editor.org/rfc/rfc3261.html#section-16.12">Loose Routing</a> </strong> mechanism will add record-routes to the SIP packet.<br />This mechanism allows a proxy to continue to be “visited” (engaged) for the duration of the dialog.<br />The <strong>loose routing proxy</strong> adds the record-route header to a SIP request to force future requests in the thick dialog to always pass through it.<br />Route headers are used to force the routing of requests through to a list of proxies.</p>
<blockquote>
<p>With the Record-routes the path is memorized and with the Routes the routing is managed properly.</p>
</blockquote>
<p>Record-routes and routes also work with the <strong>breadcrumbs mechanism</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619357285816/1r6dhA0jt.png" alt="route.png" />
<em>Thanks to  <a target="_blank" href="https://docplayer.it/2339191-Sip-session-initiation-protocol.html">https://docplayer.it/2339191-Sip-session-initiation-protocol.html</a></em></p>
<hr />
<h2 id="p-asserted-identity-remote-party-id-e-p-preferred-identity">P-Asserted-Identity Remote-Party-ID e P-Preferred-Identity</h2>
<p>The <strong>P-Asserted-Identity</strong> is used to communicate that the identity of the caller has occurred (for example using Digest Authentication, SSO with token, etc) and it is the one indicated in the P-A-I header.<br />The recipient will be able to use this information instead of providing authentication, if he considers the generator of that header an entity to be trusted, then he will be able to use that information instead of providing authentication.<br />If an entity (e.g. a carrier) receives a P-A-I from an entity it does not know (eg not you, someone on the internet), then it will not consider that identity proven, but will use some form of authentication (or simply ignore the call).</p>
<p>The <strong>Remote-PID</strong> is the old header that was used before in place of the P-A-I, now obsolete (albeit used).</p>
<p>The <strong>P-Preferred-Identity</strong> is an indication by a User Agent on which identity a receiving proxy that header should use in the P-A-I.<br />The proxy may decide to use that identity (for example if more than one can be applied), put it in P-A-I, and remove P-P-I from the outgoing INVITE.</p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619357448701/LoX6V3EKK.png" alt="sngrep.png" /></p>
<p>This is an INVITE packet. All the green one is an header; the most used we have described above.<br />In the lower part there is the description of the SDP. We will address this topic in the next episode.</p>
<hr />
<p>That’s all for this episode too.<br />Let me know what you think about it.</p>
<p>Thanks a lot for reading, sharing and comment this article.</p>
<p><em>Thanks to  <a target="_blank" href="http://undraw.co">undraw.co</a></em> for the beautiful illustration I used in the header  </p>
<p>Cheers!<br />To be continued in " <a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-3-sdp-and-rtp">part #3: SDP &amp; RTP</a> " …</p>
]]></content:encoded></item><item><title><![CDATA[VoIP: fundamentals of SIP and related topics - part #1 basic concepts of SIP]]></title><description><![CDATA[Here we are with the second appointment with the mini-series about VoIP.You can find the pilot here:
https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-pilot-0

In this episode I’ll talk about the basic concepts of SIP:

...]]></description><link>https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-1-basic-concepts-of-sip</link><guid isPermaLink="true">https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-part-1-basic-concepts-of-sip</guid><category><![CDATA[Voice]]></category><category><![CDATA[communication]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Fri, 02 Apr 2021 22:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619349793308/_jz8FFaAX.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here we are with the <strong>second</strong> appointment with the mini-series about VoIP.<br />You can find the <strong>pilot</strong> here:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-pilot-0">https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-pilot-0</a></div>
<hr />
<p>In this episode I’ll talk about the basic concepts of SIP:</p>
<ul>
<li><strong>Session Initiation Protocol</strong></li>
<li><strong>Transaction, dialog e session</strong></li>
<li><strong>Request e response</strong></li>
<li><strong>B2BUA, server e proxy SIP</strong></li>
</ul>
<hr />
<h2 id="sip-session-initiation-protocol">SIP: Session Initiation Protocol</h2>
<p>SIP is an application layer protocol; it can establish, modify and terminate a multimedia session, such as a VoIP call.
SIP mainly uses <strong>5 features</strong> in managing a communication session:</p>
<ul>
<li><strong>user location</strong>: to determine the location of the user to communicate with</li>
<li><strong>user availability</strong>: to determine the willingness of the called user to participate in the communication</li>
<li><strong>user capabilities</strong>: to determine the parameters to be used for the media stream</li>
<li><strong>session setup</strong>: to establish the session between two or more users</li>
<li><strong>session management</strong>: to manage transfers, modification of session parameters and session termination.  </li>
</ul>
<p>However, SIP is not a complete communication system, it is only one of the components to be used for complete communication.
SIP is usually used together with the <strong>SDP protocol</strong> (for the description of the multimedia session) and <strong>RTP</strong> (for the real-time transport of the multimedia streaming). We will discuss about it in part #3: SDP &amp; RTP article.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619348672955/h4Jjlr9t0.png" alt="1_db3E8pOwRPz_0oScL1dlvg.png" /></p>
<p>The main <strong>4 stages</strong> of a SIP session are:</p>
<ul>
<li><strong>location</strong>: search for the location of an endpoint</li>
<li><strong>signal</strong>: signaling the willingness to communicate with it</li>
<li><strong>negotiation</strong>: negotiation of session parameters</li>
<li><strong>teardown</strong>: session closure</li>
</ul>
<p>The <strong>registration</strong> of the VoIP account (done through the <strong>REGISTER</strong> packets) is the way in which SIP servers can acquire the <em>location information</em> (IP addresses, ports and contacts) of their users; during registration, the location server receives the REGISTERS from its users and saves (usually in a database) the association of IP address: port and contact, through a binding operation.
This data will be useful to the SIP server when it has to contact the user to route a direct call to him (<em>location</em> stage).  </p>
<p>In SIP, therefore, registration is used for the routing of <strong>incoming calls</strong> while it has no role in the authorization of outgoing calls, which is done with the Proxy-Authorization mechanism inserted within the INVITE.</p>
<hr />
<h2 id="transaction-dialog-e-session">Transaction, dialog e session</h2>
<p><strong>SIP</strong> is a <strong>transactional</strong> protocol based on a <strong>REQUEST / RESPONSE</strong> model, similar to the HTTP model.
Each SIP transaction consists of a single REQUEST and at least one RESPONSE (0 or more provisional and one or more final responses) to it.
The transaction will be destroyed after sending the final response.</p>
<p>A <strong>SIP dialog</strong> is a peer-to-peer relationship between two UA (user agents) that persists for a certain time and it’s a series of transactions between this two SIP peers.
The <strong>INVITE</strong> is the only SIP packet that can establish a dialog and the response can be either 2xx or 101–199 with To tag (a failure response does not establish a dialog).
A <strong>SIP dialog</strong> is uniquely identified by <strong>From-tag</strong>, <strong>To-tag</strong> and <strong>Call-id</strong>.</p>
<p>A <strong>SIP session</strong> is a collection of participants and media streams between them; it is participated by clients (such as SIP phones, softphones, etc) and by servers (such as SIP registrar, SIP location, SIP proxy).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619349079623/huGnHDVIr.png" alt="1_r93WkyZUdPeagPCX5CM5zA.png" /></p>
<hr />
<h2 id="request-e-response">Request e response</h2>
<p>A SIP <strong>request</strong> is identifiable by the <strong>Request-Line</strong> as the first line of packet. The Request-Line contains the <strong>method name</strong>, the <strong>Request-URI</strong> and the protocol version.</p>
<pre><code><span class="hljs-attribute">INVITE</span> sip: <span class="hljs-number">0123456</span>@<span class="hljs-number">192.0.2.124</span> SIP / <span class="hljs-number">2</span>.<span class="hljs-number">0</span>
</code></pre><p>The main methods are 6:</p>
<ul>
<li><strong>REGISTER</strong>: is used by the UA to indicate its physical location to a SIP registrar server</li>
<li><strong>INVITE</strong>: is used to start a session (or to update one in progress)</li>
<li><strong>ACK</strong>: is used to confirm that a final response to an INVITE has been received</li>
<li><strong>CANCEL</strong>: is used to terminate a pending INVITE, which did not receive a final response</li>
<li><strong>BYE</strong>: is used to end the session</li>
<li><strong>OPTIONS</strong>: is used to make a request to servers about their capacity other common methods are SUBSCRIBE, NOTIFY, PUBLISH, INFO.</li>
</ul>
<p>A SIP <strong>response</strong> is identifiable by the <strong>Status-Line</strong> as the first line of packet. The Status-Line contains the protocol version followed by the <strong>Status-Code</strong> in numerical form, followed by the reason phrasees</p>
<pre><code><span class="hljs-attribute">SIP</span> / <span class="hljs-number">2</span>.<span class="hljs-number">0</span> <span class="hljs-number">200</span> OK
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619349228545/NahqYS3l5.png" alt="1_KTntSSwTouyxebCu1W6iTg.png" /></p>
<p>The are 6 types of <strong>responses</strong> (divided in 2 macro categories):
<strong>PROVISIONAL RESPONSE</strong></p>
<ul>
<li><strong>1xx provisional response</strong>: show the receipt of the request, its processing and the status of the server</li>
</ul>
<p><strong>FINAL RESPONSE</strong> (indicate to the UAC the final response of the UAS, resulting from the processing of the REQUEST)</p>
<ul>
<li><strong>2xx success</strong>: indicate the positive reception, understanding and acceptance of the request</li>
<li><strong>3xx redirection</strong>: indicate that further actions are required to complete the request</li>
<li><strong>4xx client error</strong>: tell that the request contains incorrect syntax or that it cannot be satisfied by this server</li>
<li><strong>5xx server error</strong>: tell that this server cannot fulfill an apparent valid request</li>
<li><strong>6xx global error</strong>: tell that the request cannot be satisfied by any server</li>
</ul>
<hr />
<h2 id="b2bua-server-e-proxy-sip">B2BUA, server e proxy SIP</h2>
<p>A <strong>B2BUA</strong> (back to back user agent) is a logical entity that receives SIP requests and processes them as if it were a UAS (user agent server), therefore as if it were the ultimate recipient of the request.
To know how to respond to the request, a B2BUA also acts simultaneously as a UAC (user agent client) and generates new requests; it will then manage a dialog with the UAC from which the requests arrive and a dialog with the final UAS that must receive them.
A <strong>B2BUA</strong> maintains the status of the dialog and will have to participate in every request of that dialog.
<strong>Why use a B2BUA</strong>: it is used when you need to have full control of the requests arriving on your SIP server in order to build on it the business logic (<em>for example a billing system</em>).</p>
<p>A <strong>SIP server</strong> is a network element that receives SIP requests and sends replies.
Some examples of SIP servers: proxy, UAS, registrar server.</p>
<p>A <strong>SIP proxy</strong> is an intermediary entity that acts as a server and client with the purpose of getting requests to clients.
The tasks of a proxy are:</p>
<ul>
<li><strong>routing management</strong>: its job is to find the way to get the request to the right client</li>
<li><strong>policy compliance management</strong>: for example checking that a user can make the call</li>
</ul>
<hr />
<p>That’s all for this episode too.<br />Let me know what you think about it.</p>
<p>Thanks a lot for reading, sharing and comment this article.</p>
<p><em>Thanks to  <a target="_blank" href="http://undraw.co">undraw.co</a></em> for the beautiful illustration I used in the header  </p>
<p>Cheers!<br />To be continued in " <a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-2-the-basic-sip-headers">part #2: the basic SIP headers</a> " …</p>
]]></content:encoded></item><item><title><![CDATA[VoIP: fundamentals of SIP and related topics - pilot #0]]></title><description><![CDATA[VoIP stands for Voice over IP. VoIP refers to communications that no longer take place through a traditional telephone network, but through an IP network.
More specifically, VoIP refers to the set of application layer communication protocols that mak...]]></description><link>https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-pilot-0</link><guid isPermaLink="true">https://blog.gt0.dev/voip-fundamentals-of-sip-and-related-topics-pilot-0</guid><category><![CDATA[Voice]]></category><category><![CDATA[tips]]></category><dc:creator><![CDATA[Giovanni Tommasini]]></dc:creator><pubDate>Sat, 27 Mar 2021 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618156269344/LPbJhwkVb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>VoIP</strong> stands for <strong>V</strong>oice <strong>o</strong>ver <strong>IP</strong>. <strong>VoIP</strong> refers to communications that no longer take place through a traditional telephone network, but through an IP network.</p>
<p>More specifically, <strong>VoIP</strong> refers to the set of application layer communication protocols that make this type of communication possible.<br />The <strong>information</strong> (both the signaling to establish, manage and close the call, and the voice), instead of traveling on an analog telephone line, crosses any network based on an IP protocol.<br />The communication that the <strong>VoIP</strong> system allows to obtain is of the <strong>real-time audio-video</strong>, unicast or multicast type (therefore video calls and videoconferences, for example), and allows you to easily reach any type of user.<br />It therefore offers the possibility to make and receive calls from other VoIP numbers, analogue numbers, national numbers, international numbers, fixed and mobile users, all toll-free numbers and emergency numbers.</p>
<p> <a target="_blank" href="https://medium.com/r/?url=https%3A%2F%2Fgetvoip.com%2Fblog%2F2014%2F01%2F27%2Fhistory-of-voip-and-internet-telephones%2F">Here</a> , thanks to  <a target="_blank" href="https://medium.com/r/?url=http%3A%2F%2Fgetvoip.com">getvoip.com</a> , you can find a nice and complete article on the birth and evolution of the VoIP, from 1928 to today.</p>
<p>In the last years the development of <strong>VoIP</strong> has been very fast and its technology is constantly evolving; all of this was possible thanks to the widespread diffusion of high performance and broadband internet connections.</p>
<p>For <strong>data transport</strong> (the voice), in the vast majority of <strong>VoIP</strong> implementations, a set of communication protocols such as <strong>RTP</strong> (Real-time Transport Protocol) over <strong>UDP</strong> (User Datagram Protocol) over <strong>IP</strong> (Internet Protocol) are adopted. The use of UDP instead of TCP is justified by the fact that a real-time communication such as voice cannot tolerate additional or too high delays or latencies due to the retransmission of lost packets.<br />For the <strong>signaling</strong> (that is everything that concerns the reaching of the user, the establishment of the call, the maintenance of communication and then the closure of the call) there is a vast dominance of the use of the <strong>SIP protocol</strong>, over both <strong>UDP</strong> and <strong>TCP</strong>.</p>
<hr />
<p>The web is full of article and video about this topic.<br />One of the most viewed YouTube video is this one</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=2x3Ie6VZ_sg">https://www.youtube.com/watch?v=2x3Ie6VZ_sg</a></div>
<hr />
<p>In this <em>mini-series of articles</em> I want to give my contribution on this topic. 
The series will be divided into the following parts:</p>
<ul>
<li>pilot #0: <em>(the article you are reading) a brief introduction to the mini-series</em></li>
<li><a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-1-basic-concepts-of-sip">part #1: <em>basic concepts of SIP</em></a> </li>
<li><a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-2-the-basic-sip-headers">part #2: <em>the basic SIP headers</em></a> </li>
<li><a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-3-sdp-and-rtp">part #3: <em>SDP &amp; RTP</em></a> </li>
<li><a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-4-ua-pbx-standard-configurations">part #4: <em>UA PBX, standard configurations and some security tips</em></a> </li>
<li><a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-5-the-main-tools-for-working-with-voip">part #5: <em>the main tools for working with VoIP</em></a> </li>
<li><a target="_blank" href="https://blog.giovannitommasini.info/voip-fundamentals-of-sip-and-related-topics-part-6-audio-problems-and-the-quality-of-a-voip-call">part #6: audio problems and the quality of a VoIP call</a></li>
<li>season finale #7: <em>final conclusions </em></li>
</ul>
<p>Let me know if this is an interest topic to you and if you like the lineup or if there are any topics / insights that you would like to speak about.  </p>
<blockquote>
<p>Writing about a topic is a way to "understand if I understand", to collect contributions (I hope there will be many comments that will confirm what I have written and many comments that will correct me) and to help the sharing of knowledge and I love all of this stuff!</p>
</blockquote>
<hr />
<p>Thanks a lot for reading, sharing and comment this article.</p>
<p><em>Thanks to  <a target="_blank" href="http://undraw.co">undraw.co</a></em> for the beautiful illustration I used in the header</p>
<p>Cheers!</p>
]]></content:encoded></item></channel></rss>