<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Hang Hu - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Hang Hu - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:23:58 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/huhuhang/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Schedule Tasks in Red Hat Enterprise Linux ]]>
                </title>
                <description>
                    <![CDATA[ Red Hat Enterprise Linux (RHEL) is a leading enterprise-grade Linux distribution widely regarded as the gold standard for mission-critical server environments. It provides robust, secure, and scalable solutions for organizations ranging from small bu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-schedule-tasks-in-red-hat-enterprise-linux/</link>
                <guid isPermaLink="false">685c9989f2073d62fe9b82f5</guid>
                
                    <category>
                        <![CDATA[ RHEL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ rhcsa ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hang Hu ]]>
                </dc:creator>
                <pubDate>Thu, 26 Jun 2025 00:51:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750869114329/79072c41-988a-41f2-9e2f-25618d78fefc.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Red Hat Enterprise Linux (RHEL) is a leading enterprise-grade Linux distribution widely regarded as the gold standard for mission-critical server environments. It provides robust, secure, and scalable solutions for organizations ranging from small businesses to Fortune 500 companies, powering everything from web servers and databases to cloud infrastructure and containerized applications.</p>
<p>You can use RHEL's task scheduling capabilities in scenarios like automating system maintenance (for example, log rotation or backup operations), managing routine administrative tasks (like user account cleanup or security updates), or orchestrating complex workflows in enterprise environments. These scheduling tools are essential for maintaining system health and ensuring that critical operations run without manual intervention.</p>
<p>For system administrators, think of task scheduling as the backbone of automated system management, enabling you to set up processes that run reliably in the background while you focus on more strategic initiatives. Its power lies in its flexibility and reliability, making it an indispensable skill for anyone managing Linux systems in production environments.</p>
<p>In this tutorial, you’ll learn how to schedule tasks in Red Hat Enterprise Linux using various built-in tools and techniques. This content is part of <strong>Schedule Future Tasks</strong>, which is Chapter 2 of the <a target="_blank" href="https://labex.io/courses/red-hat-system-administration-rh134-labs">Red Hat System Administration (RH134) course</a>. RH134 is a fundamental course for the Red Hat Certified System Administrator (RHCSA) certification, one of the most respected credentials in the Linux administration field.</p>
<p>This hands-on tutorial provides practical experience with the scheduling concepts covered in the RH134 curriculum, giving you the skills needed to automate tasks effectively in enterprise RHEL environments.</p>
<h3 id="heading-heres-what-well-cover">Here's what we'll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-schedule-a-one-time-job-with-at">How to Schedule a One-time Job with 'at'</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-at-jobs">How to Manage 'at' jobs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-schedule-recurring-user-jobs-with-crontab">How to Schedule Recurring User Jobs with 'crontab'</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-user-crontab-entries">How to Manage User 'crontab' Entries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-schedule-recurring-system-jobs-with-cron-directories">How to Schedule Recurring System Jobs with cron Directories</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-configure-systemd-timers-for-recurring-tasks">How to Configure systemd Timers for Recurring Tasks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-temporary-files-with-systemd-tmpfiles">How to Manage Temporary Files with systemd-tmpfiles</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>This tutorial is designed to be beginner-friendly! You just need basic familiarity with using the Linux command line. If you can navigate directories and run simple commands, you're ready to start.</p>
<p>For those looking to deepen their RHEL knowledge, the <a target="_blank" href="https://labex.io/skilltrees/rhel">RHEL Skill Tree</a> offers comprehensive hands-on labs including <a target="_blank" href="https://labex.io/courses/red-hat-system-administration-rh124-labs">RH124</a>, <a target="_blank" href="https://labex.io/courses/red-hat-system-administration-rh134-labs">RH134</a>, <a target="_blank" href="https://labex.io/courses/red-hat-enterprise-linux-automation-with-ansible-rh294">RH294</a>, and other courses for RHCSA and RHCE certifications.</p>
<p>Don't worry if you're new to Red Hat Enterprise Linux – I'll explain everything step by step, and these concepts work on most Linux distributions too.</p>
<h2 id="heading-how-to-schedule-a-one-time-job-with-at"><strong>How to Schedule a One-time Job with 'at'</strong></h2>
<p>First, let’s learn how to schedule a job to run once at a future time using the <code>at</code> command. The <code>at</code> command is useful for executing commands that don’t need to be run repeatedly. We will schedule a simple job, inspect its details, and then remove it.</p>
<p>In this tutorial, we will work directly on the local system to learn task scheduling. You’ll execute all commands in your current terminal environment.</p>
<p>Let's schedule a job to print the current date and time into a file named <code>~/myjob.txt</code> in your home directory. We'll schedule it to run 3 minutes from now:</p>
<pre><code class="lang-bash">at now + 3 minutes &lt;&lt; EOF
date &gt; ~/myjob.txt
EOF
</code></pre>
<p>The <code>warning: commands will be executed using /bin/sh</code> message is normal. The <code>job N at ...</code> output indicates the job number and the scheduled execution time. Make a note of the job number, as you will need it later.</p>
<p>Next, let's schedule another job interactively. This method is useful for entering multiple commands or more complex scripts. We will schedule a job to append "Hello from at job!" to <code>~/at_output.txt</code> 5 minutes from now:</p>
<pre><code class="lang-bash">at now + 5 minutes
</code></pre>
<p>After typing the command and pressing Enter, you will see an <code>at&gt;</code> prompt. Type your command and then press <code>Ctrl+d</code> to finish:</p>
<pre><code class="lang-bash">at &gt; <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello from at job!"</span> &gt;&gt; ~/at_output.txt
at &gt; Ctrl+d
</code></pre>
<p>To view the jobs currently in the <code>at</code> queue, use the <code>atq</code> command. This command lists all pending <code>at</code> jobs for the current user.</p>
<pre><code class="lang-bash">atq
</code></pre>
<p>The output will show the job number, the scheduled time, the queue, and the user who scheduled it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750726190789/d2dd54c0-80a0-4bb2-8561-3114bb279387.png" alt="Output of atq command showing scheduled jobs" class="image--center mx-auto" width="672" height="333" loading="lazy"></p>
<p>You can inspect the commands that a specific <code>at</code> job will run using the <code>at -c</code> command followed by the job number. Replace <code>N</code> with one of the job numbers you noted earlier.</p>
<pre><code class="lang-bash">at -c N
</code></pre>
<p>This command will display the shell script that <code>at</code> will execute for that job. You should see the <code>date &gt; ~/myjob.txt</code> or <code>echo "Hello from at job!" &gt;&gt; ~/at_output.txt</code> command within the output.</p>
<p>Finally, to remove a scheduled <code>at</code> job, use the <code>atrm</code> command followed by the job number. Let's remove the first job we scheduled. Replace <code>N</code> with the job number of your first job.</p>
<pre><code class="lang-bash">atrm N
</code></pre>
<p>After removing the job, you can use <code>atq</code> again to verify that it is no longer in the queue.</p>
<pre><code class="lang-bash">atq
</code></pre>
<p>You should now only see the second job (if it hasn't executed yet) or an empty queue if both jobs have been removed or executed.</p>
<p>This completes the first step of scheduling one-time jobs with the <code>at</code> command.</p>
<h2 id="heading-how-to-manage-at-jobs"><strong>How to Manage 'at' jobs</strong></h2>
<p>Now, let’s delve deeper into managing <code>at</code> jobs, including scheduling jobs with different queues and verifying their execution. Understanding <code>at</code> queues can be useful for prioritizing tasks or separating different types of one-time jobs.</p>
<p>We will continue working on the local system to explore more advanced <code>at</code> job management features.</p>
<p>The <code>at</code> command allows you to specify a queue using the <code>-q</code> option. Queues are single letters from <code>a</code> to <code>z</code>. Queue <code>a</code> is the default, and jobs in queues <code>a</code> through <code>z</code> are executed with decreasing niceness (priority). Queue <code>a</code> has the highest priority, and queue <code>z</code> has the lowest. Queue <code>b</code> is reserved for batch jobs.</p>
<p>Let's schedule a job in queue <code>g</code> (a lower priority queue) to run in 2 minutes. This job will create a file named <code>~/queue_g_job.txt</code> with a timestamp:</p>
<pre><code class="lang-bash">at -q g now + 2 minutes &lt;&lt; EOF
date &gt; ~/queue_g_job.txt
EOF
</code></pre>
<p>You will see output similar to <code>job N at ...</code>. Note down this job number.</p>
<p>Next, let's schedule another job, this time in queue <code>b</code> (batch queue), which is typically used for jobs that can run when system load is low. This job will append "Batch job executed!" to <code>~/batch_job.txt</code>. We'll schedule it to run 4 minutes from now:</p>
<pre><code class="lang-bash">at -q b now + 4 minutes &lt;&lt; EOF
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Batch job executed!"</span> &gt;&gt; ~/batch_job.txt
EOF
</code></pre>
<p>Again, note down the job number.</p>
<p>To see all pending jobs, including those in different queues, use <code>atq</code>.</p>
<pre><code class="lang-bash">atq
</code></pre>
<p>You should now see both jobs listed, with their respective queue letters (<code>g</code> and <code>b</code>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750726218380/bcc9d551-0530-48d1-bf7f-46073c6f77a6.png" alt="Output of atq command showing scheduled jobs" class="image--center mx-auto" width="589" height="325" loading="lazy"></p>
<p>Now, wait for your scheduled jobs to execute. Wait for at least 5 minutes to allow all jobs to complete. You can check if the files created by your <code>at</code> jobs exist and contain the expected content.</p>
<p>Check <code>~/queue_g_job.txt</code>:</p>
<pre><code class="lang-bash">cat ~/queue_g_job.txt
</code></pre>
<p>You should see a date and time string.</p>
<p>Check <code>~/batch_job.txt</code>:</p>
<pre><code class="lang-bash">cat ~/batch_job.txt
</code></pre>
<p>You should see "Batch job executed!".</p>
<p>If the files are not present or empty, it might mean the jobs haven't executed yet, or there was an issue with the command. You can re-check <code>atq</code> to see if they are still pending.</p>
<h2 id="heading-how-to-schedule-recurring-user-jobs-with-crontab"><strong>How to Schedule Recurring User Jobs with 'crontab'</strong></h2>
<p>Next, you’ll learn how to schedule recurring tasks for a specific user using <code>crontab</code>. Unlike <code>at</code> jobs, which run once, <code>cron</code> jobs run repeatedly at specified intervals. This is ideal for routine maintenance, data backups, or generating reports.</p>
<p>We will continue working on the local system to learn about user crontab management.</p>
<p>The <code>crontab</code> command allows users to create, edit, and view their own <code>cron</code> jobs. Each user has their own <code>crontab</code> file.</p>
<p>To edit your <code>crontab</code> file, use the <code>crontab -e</code> command. This will open your <code>crontab</code> file in the default text editor (usually <code>vim</code>).</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p><strong>Vim editor instructions:</strong></p>
<ul>
<li><p>Press <code>i</code> to enter insert mode (you'll see <code>-- INSERT --</code> at the bottom)</p>
</li>
<li><p>Use arrow keys to navigate</p>
</li>
<li><p>To save and exit: Press <code>Esc</code> to exit insert mode, then type <code>:wq</code> and press <code>Enter</code></p>
</li>
<li><p>To exit without saving: Press <code>Esc</code>, then type <code>:q!</code> and press <code>Enter</code></p>
</li>
</ul>
<p>Inside the editor, you will add a new line to define your <code>cron</code> job. A <code>cron</code> entry has five time-and-date fields, followed by the command to be executed. The fields are:</p>
<ul>
<li><p><strong>Minute (0-59)</strong></p>
</li>
<li><p><strong>Hour (0-23)</strong></p>
</li>
<li><p><strong>Day of Month (1-31)</strong></p>
</li>
<li><p><strong>Month (1-12)</strong></p>
</li>
<li><p><strong>Day of Week (0-7, where 0 or 7 is Sunday)</strong></p>
</li>
</ul>
<p>You can use <code>*</code> as a wildcard to mean "every" for a field, or <code>/</code> to specify step values (for example, <code>*/5</code> for every 5 minutes).</p>
<p>Let's schedule a job that appends the current date and time to a file named <code>~/my_cron_log.txt</code> every minute. This will allow us to quickly observe the <code>cron</code> job in action.</p>
<p>Follow these steps in Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line to the <code>crontab</code> file:</p>
</li>
</ol>
<pre><code class="lang-bash">* * * * * /usr/bin/date &gt;&gt; ~/my_cron_log.txt
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>You should see a message indicating that a new <code>crontab</code> has been installed:</p>
<pre><code class="lang-plaintext">crontab: installing new crontab
</code></pre>
<p>To verify that your <code>cron</code> job has been successfully added, you can list your <code>crontab</code> entries using the <code>crontab -l</code> command:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should see the line you just added:</p>
<pre><code class="lang-plaintext">* * * * * /usr/bin/date &gt;&gt; ~/my_cron_log.txt
</code></pre>
<p>Now, wait for a minute or two to allow the <code>cron</code> job to execute at least once. You can check the current time to see when the next minute mark will occur:</p>
<pre><code class="lang-bash">date
</code></pre>
<p>After waiting for at least two minutes to allow the cron job to execute a couple of times, check the content of the <code>~/my_cron_log.txt</code> file.</p>
<pre><code class="lang-bash">cat ~/my_cron_log.txt
</code></pre>
<p>You should see one or more lines, each containing a date and time, indicating that your <code>cron</code> job has executed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1750726409656/bfd85cf0-316a-4c1d-89c2-0d60c30cd33f.png" alt="Cron job output in log file" class="image--center mx-auto" width="607" height="281" loading="lazy"></p>
<pre><code class="lang-plaintext">Mon Apr 8 10:30:01 AM EDT 2025
Mon Apr 8 10:31:01 AM EDT 2025
</code></pre>
<h2 id="heading-how-to-manage-user-crontab-entries"><strong>How to Manage User 'crontab' Entries</strong></h2>
<p>Now you will learn more advanced techniques for managing user <code>crontab</code> entries, including editing existing jobs, adding multiple jobs, and understanding special <code>cron</code> strings. Effective <code>crontab</code> management is crucial for automating routine tasks.</p>
<p>We will continue working on the local system to explore advanced crontab management techniques.</p>
<p>Let's start by adding a new <code>cron</code> job. This job will append "Hello from cron!" to <code>~/cron_messages.txt</code> every two minutes.</p>
<p>Open your <code>crontab</code> for editing:</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p>In Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line to the <code>crontab</code> file:</p>
</li>
</ol>
<pre><code class="lang-bash">*/2 * * * * <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello from cron!"</span> &gt;&gt; ~/cron_messages.txt
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>Verify that the entry is added:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should see the newly added line.</p>
<p>Now, let's add another <code>cron</code> job that runs daily at 08:00 AM. This job will record the disk usage of your home directory to <code>~/disk_usage.log</code>.</p>
<p>Open your <code>crontab</code> for editing again:</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p>In Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line below the previous one:</p>
</li>
</ol>
<pre><code class="lang-bash">0 8 * * * du -sh ~ &gt;&gt; ~/disk_usage.log
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>Verify that both entries are present:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should now see both <code>cron</code> jobs listed.</p>
<p><code>cron</code> also supports special strings that can simplify common schedules. These include <code>@reboot</code>, <code>@yearly</code>, <code>@annually</code>, <code>@monthly</code>, <code>@weekly</code>, <code>@daily</code>, <code>@midnight</code>, and <code>@hourly</code>. For example, <code>@hourly</code> is equivalent to <code>0 * * * *</code>.</p>
<p>Let's add a job that runs hourly and records the system uptime to <code>~/uptime_log.txt</code>.</p>
<p>Open your <code>crontab</code> for editing:</p>
<pre><code class="lang-bash">crontab -e
</code></pre>
<p>In Vim:</p>
<ol>
<li><p>Press <code>i</code> to enter insert mode</p>
</li>
<li><p>Add the following line:</p>
</li>
</ol>
<pre><code class="lang-bash">@hourly uptime &gt;&gt; ~/uptime_log.txt
</code></pre>
<ol start="3">
<li><p>Press <code>Esc</code> to exit insert mode</p>
</li>
<li><p>Type <code>:wq</code> and press <code>Enter</code> to save and exit</p>
</li>
</ol>
<p>Verify all three entries:</p>
<pre><code class="lang-bash">crontab -l
</code></pre>
<p>You should now see all three <code>cron</code> jobs.</p>
<p>To demonstrate the effect of these jobs, we will wait for a short period. Since the jobs are scheduled at different intervals, we won't see all of them execute immediately, but we can verify the setup.</p>
<p>Wait for at least 3 minutes to allow the <code>*/2</code> job to run at least once.</p>
<p>Check the <code>~/cron_messages.txt</code> file:</p>
<pre><code class="lang-bash">cat ~/cron_messages.txt
</code></pre>
<p>You should see at least one "Hello from cron!" message.</p>
<pre><code class="lang-plaintext">Hello from cron!
</code></pre>
<p>The <code>~/disk_usage.log</code> and <code>~/uptime_log.txt</code> files might not be created yet, depending on the current time, as they are scheduled for daily and hourly execution, respectively. The important part is that their entries are correctly configured in your <code>crontab</code>.</p>
<h2 id="heading-how-to-schedule-recurring-system-jobs-with-cron-directories"><strong>How to Schedule Recurring System Jobs with</strong> <code>cron</code> <strong>Directories</strong></h2>
<p>In this step, you will learn how to schedule recurring system-wide tasks using <code>cron</code> directories. Unlike user <code>crontab</code> entries, which are specific to a user, system <code>cron</code> jobs are managed by the root user and affect the entire system. These are typically used for system maintenance, log rotation, and other administrative tasks.</p>
<p>We will continue working on the local system to explore system-wide cron job configuration.</p>
<p>System-wide <code>cron</code> jobs are defined in <code>/etc/crontab</code> or by placing scripts in specific directories:</p>
<ul>
<li><p><code>/etc/cron.hourly/</code>: Scripts in this directory run once an hour.</p>
</li>
<li><p><code>/etc/cron.daily/</code>: Scripts in this directory run once a day.</p>
</li>
<li><p><code>/etc/cron.weekly/</code>: Scripts in this directory run once a week.</p>
</li>
<li><p><code>/etc/cron.monthly/</code>: Scripts in this directory run once a month.</p>
</li>
</ul>
<p>These directories are processed by the <code>run-parts</code> utility, which executes all executable files within them.</p>
<p>To manage system <code>cron</code> jobs, you need root privileges. Since the labex user has sudo access, we can use <code>sudo</code> for the required commands.</p>
<p>Let's create a simple script that logs a message to the system log. We will place this script in <code>/etc/cron.hourly/</code> to make it run hourly.</p>
<p>First, create the script file <code>/etc/cron.hourly/my_hourly_script</code>:</p>
<pre><code class="lang-bash">sudo nano /etc/cron.hourly/my_hourly_script
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
logger <span class="hljs-string">"Hourly cron job executed at <span class="hljs-subst">$(date)</span>"</span>
</code></pre>
<p>Save and exit the editor (<code>Ctrl+o</code>, <code>Enter</code>, <code>Ctrl+x</code> in <code>nano</code>).</p>
<p>Next, you need to make the script executable. Without execute permissions, <code>run-parts</code> will ignore it.</p>
<pre><code class="lang-bash">sudo chmod +x /etc/cron.hourly/my_hourly_script
</code></pre>
<p>Now, let's verify that the script is executable:</p>
<pre><code class="lang-bash">ls -l /etc/cron.hourly/my_hourly_script
</code></pre>
<p>You should see <code>x</code> in the permissions, for example: <code>-rwxr-xr-x</code>.</p>
<p>Since <code>cron.hourly</code> jobs run once an hour, we can't wait for a full hour to verify its execution in this tutorial. But we can manually trigger the <code>run-parts</code> command for the hourly directory to simulate its execution.</p>
<pre><code class="lang-bash">sudo run-parts /etc/cron.hourly/
</code></pre>
<p>This command will execute all executable scripts in <code>/etc/cron.hourly/</code>. The script we created uses the <code>logger</code> command to write messages to the system log.</p>
<p>In a real RHEL system, you would be able to check the system logs using <code>journalctl</code> or <code>/var/log/messages</code> to verify that the script executed successfully.</p>
<p>This completes the system cron job management step. The script will remain in place and would execute hourly in a real system environment.</p>
<h2 id="heading-how-to-configure-systemd-timers-for-recurring-tasks"><strong>How to Configure</strong> <code>systemd</code> <strong>Timers for Recurring Tasks</strong></h2>
<p>Next, you will learn about <code>systemd</code> timers, which are a modern alternative to <code>cron</code> for scheduling tasks on Linux systems. <code>systemd</code> timers offer more flexibility and better integration with the <code>systemd</code> ecosystem.</p>
<p><code>systemd</code> timers work in conjunction with <code>systemd</code> service units. A timer unit (<code>.timer</code> file) defines when a task should run, and a service unit (<code>.service</code> file) defines what task should be executed.</p>
<p>We will continue working on the local system to explore systemd timer configuration.</p>
<p>You will need root privileges to create <code>systemd</code> unit files in system directories. Since the labex user has sudo access, we can use <code>sudo</code> for the required commands.</p>
<p>Let's create a simple service that logs a message to a file. We will place this service unit file in <code>/etc/systemd/system/</code> which is where custom service units are typically stored.</p>
<p>Create the service unit file <code>/etc/systemd/system/my-custom-task.service</code>:</p>
<pre><code class="lang-bash">sudo nano /etc/systemd/system/my-custom-task.service
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-ini"><span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=My Custom Scheduled Task

<span class="hljs-section">[Service]</span>
<span class="hljs-attr">Type</span>=<span class="hljs-literal">on</span>eshot
<span class="hljs-attr">ExecStart</span>=/bin/bash -c <span class="hljs-string">'echo "My custom task executed at $(date)" &gt;&gt; /var/log/my-custom-task.log'</span>
</code></pre>
<p>Save and exit the editor (<code>Ctrl+o</code>, <code>Enter</code>, <code>Ctrl+x</code> in <code>nano</code>).</p>
<p>Next, create the timer unit file <code>/etc/systemd/system/my-custom-task.timer</code>. This timer will activate our service every 5 minutes.</p>
<pre><code class="lang-bash">sudo nano /etc/systemd/system/my-custom-task.timer
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-ini"><span class="hljs-section">[Unit]</span>
<span class="hljs-attr">Description</span>=Run My Custom Scheduled Task every <span class="hljs-number">5</span> minutes

<span class="hljs-section">[Timer]</span>
<span class="hljs-attr">OnCalendar</span>=*:<span class="hljs-number">0</span>/<span class="hljs-number">5</span>
<span class="hljs-attr">Persistent</span>=<span class="hljs-literal">true</span>

<span class="hljs-section">[Install]</span>
<span class="hljs-attr">WantedBy</span>=timers.target
</code></pre>
<p>Save and exit the editor.</p>
<p><strong>Explanation of</strong> <code>OnCalendar</code>:</p>
<ul>
<li><p><code>*:0/5</code> means "every 5 minutes".</p>
<ul>
<li><p><code>*</code> for year, month, day, hour (any value).</p>
</li>
<li><p><code>0/5</code> for minute, meaning starting at minute 0, every 5 minutes (0, 5, 10, ..., 55).</p>
</li>
</ul>
</li>
</ul>
<p>In a typical <code>systemd</code> environment, you would now run <code>systemctl daemon-reload</code> to make <code>systemd</code> aware of the new unit files, and then <code>systemctl enable --now my-custom-task.timer</code> to start the timer.</p>
<p>Let's verify the existence of the created files:</p>
<pre><code class="lang-bash">ls -l /etc/systemd/system/my-custom-task.service
ls -l /etc/systemd/system/my-custom-task.timer
</code></pre>
<p>You should see output indicating that both files exist.</p>
<p>To simulate the execution of the service, you can manually run the command defined in <code>ExecStart</code>:</p>
<pre><code class="lang-bash">sudo /bin/bash -c <span class="hljs-string">'echo "My custom task executed at $(date)" &gt;&gt; /var/log/my-custom-task.log'</span>
</code></pre>
<p>Now, check the log file to see the output:</p>
<pre><code class="lang-bash">sudo cat /var/<span class="hljs-built_in">log</span>/my-custom-task.log
</code></pre>
<p>You should see the message you just logged:</p>
<pre><code class="lang-plaintext">My custom task executed at Tue Jun 10 06:54:40 UTC 2025
</code></pre>
<p>This completes the systemd timer configuration step. The service and timer unit files will remain in place for reference.</p>
<h2 id="heading-how-to-manage-temporary-files-with-systemd-tmpfiles"><strong>How to Manage Temporary Files with</strong> <code>systemd-tmpfiles</code></h2>
<p>Now you’ll learn how to manage temporary files and directories using <code>systemd-tmpfiles</code>. This utility is part of <code>systemd</code> and is responsible for creating, deleting, and cleaning up volatile and temporary files and directories. It's commonly used to manage <code>/tmp</code>, <code>/var/tmp</code>, and other temporary storage locations, ensuring that old files are removed periodically.</p>
<p>We will continue working on the local system to explore systemd-tmpfiles configuration.</p>
<p>You will need root privileges to configure <code>systemd-tmpfiles</code>. Since the labex user has sudo access, we can use <code>sudo</code> for the required commands.</p>
<p><code>systemd-tmpfiles</code> reads configuration files from <code>/etc/tmpfiles.d/</code> and <code>/usr/lib/tmpfiles.d/</code>. These files define rules for creating, deleting, and managing files and directories.</p>
<p>Let's create a custom configuration file to manage a new temporary directory. We will create a directory <code>/run/my_temp_dir</code> and configure <code>systemd-tmpfiles</code> to clean files older than 1 minute from it.</p>
<p>Create the configuration file <code>/etc/tmpfiles.d/my_temp_dir.conf</code>:</p>
<pre><code class="lang-bash">sudo nano /etc/tmpfiles.d/my_temp_dir.conf
</code></pre>
<p>Add the following content to the file:</p>
<pre><code class="lang-bash">d /run/my_temp_dir 0755 labex labex 1m
</code></pre>
<p><strong>Explanation of the line:</strong></p>
<ul>
<li><p><code>d</code>: Specifies that this entry defines a directory.</p>
</li>
<li><p><code>/run/my_temp_dir</code>: The path to the directory.</p>
</li>
<li><p><code>0755</code>: The permissions for the directory.</p>
</li>
<li><p><code>labex labex</code>: The owner and group for the directory.</p>
</li>
<li><p><code>1m</code>: The age after which files in this directory should be deleted (1 minute).</p>
</li>
</ul>
<p>Save and exit the editor (<code>Ctrl+o</code>, <code>Enter</code>, <code>Ctrl+x</code> in <code>nano</code>).</p>
<p>Now, let's tell <code>systemd-tmpfiles</code> to apply this configuration. The <code>--create</code> option will create the directory if it doesn't exist.</p>
<pre><code class="lang-bash">sudo systemd-tmpfiles --create /etc/tmpfiles.d/my_temp_dir.conf
</code></pre>
<p>Verify that the directory has been created with the correct permissions and ownership:</p>
<pre><code class="lang-bash">ls -ld /run/my_temp_dir
</code></pre>
<p>You should see output similar to:</p>
<pre><code class="lang-plaintext">drwxr-xr-x 2 labex labex 6 Jun 10 06:55 /run/my_temp_dir
</code></pre>
<p>Next, let's create a test file inside this new temporary directory:</p>
<pre><code class="lang-bash">sudo touch /run/my_temp_dir/test_file.txt
</code></pre>
<p>Verify the file exists:</p>
<pre><code class="lang-bash">ls -l /run/my_temp_dir/test_file.txt
</code></pre>
<p>Now, we need to wait for more than 1 minute for the file to become "old" according to our configuration. Wait for at least 70 seconds (1 minute and 10 seconds).</p>
<p>After waiting for more than 1 minute, we will manually run <code>systemd-tmpfiles</code> with the <code>--clean</code> option to trigger the cleanup process based on our configuration.</p>
<pre><code class="lang-bash">sudo systemd-tmpfiles --clean /etc/tmpfiles.d/my_temp_dir.conf
</code></pre>
<p>Finally, check if the <code>test_file.txt</code> has been removed:</p>
<pre><code class="lang-bash">ls -l /run/my_temp_dir/test_file.txt
</code></pre>
<p>You should get a "No such file or directory" error, indicating that <code>systemd-tmpfiles</code> successfully cleaned up the old file.</p>
<p>This completes configuring the systemd-tmpfiles. The configuration file and temporary directory will remain in place for reference.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>In this tutorial, you learned how to schedule and manage one-time tasks using the <code>at</code> command, including scheduling jobs interactively and non-interactively, viewing the <code>at</code> queue with <code>atq</code>, and deleting pending jobs with <code>atrm</code>. You also learned how to schedule recurring user-specific tasks using <code>crontab</code>, including how to edit, list, and remove cron jobs, and you learned the cron syntax for specifying execution times.</p>
<p>We also demonstrated how to schedule system-wide recurring tasks by placing scripts in standard cron directories (<code>/etc/cron.hourly</code>, <code>/etc/cron.daily</code>, etc.) and how to create custom cron jobs in <code>/etc/cron.d</code>.</p>
<p>Finally, you explored advanced task scheduling with <code>systemd</code> timers, learning to create and enable service and timer units for recurring tasks, and how to manage temporary files and directories using <code>systemd-tmpfiles</code> for automated cleanup.</p>
<p>This comprehensive tutorial provided practical experience in managing diverse task scheduling needs on RHEL systems, from simple one-off commands to complex recurring system processes.</p>
<p>To practice the operations from this tutorial, try the interactive hands-on lab: <a target="_blank" href="https://labex.io/labs/rhel-schedule-tasks-in-red-hat-enterprise-linux-588897?course=red-hat-system-administration-rh134-labs">Schedule Tasks in Red Hat Enterprise Linux</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Wireshark Filters to Analyze Your Network Traffic ]]>
                </title>
                <description>
                    <![CDATA[ Wireshark is an open-source tool widely regarded as the gold standard for network packet analysis. It allows you to capture live network traffic or inspect pre-recorded capture files, breaking down the data into individual packets for detailed examin... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-wireshark-filters-to-analyze-network-traffic/</link>
                <guid isPermaLink="false">67ee83d004f007db33e0f920</guid>
                
                    <category>
                        <![CDATA[ #cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Wireshark ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hang Hu ]]>
                </dc:creator>
                <pubDate>Thu, 03 Apr 2025 12:49:20 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743684532493/cc26aa99-fc7a-4b47-ab16-60dac77561fd.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Wireshark is an open-source tool widely regarded as the gold standard for network packet analysis. It allows you to capture live network traffic or inspect pre-recorded capture files, breaking down the data into individual packets for detailed examination.</p>
<p>You can use Wireshark in scenarios like troubleshooting network performance issues (for example, slow connections or dropped packets), investigating suspicious activity (like detecting malware or unauthorized access), or learning how protocols like HTTP, TCP, or DNS function in real-world environments.</p>
<p>For beginners, think of it as a window into the invisible world of network communication, revealing what’s happening behind the scenes when you browse the web, send an email, or stream a video. Its power lies in its ability to provide granular insights, making it an indispensable tool for network administrators, cybersecurity enthusiasts, and anyone curious about how networks operate.</p>
<p>In this tutorial, you will learn how to use Wireshark display filters to analyze network traffic and spot potential security threats. Wireshark is a powerful network protocol analyzer that can capture and dissect network packets, which is crucial for cybersecurity professionals.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-start-wireshark-and-analyze-network-traffic">How to Start Wireshark and Analyze Network Traffic</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-work-with-network-capture-files">How to Work with Network Capture Files</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-wireshark-interface">Understanding the Wireshark Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-and-applying-basic-display-filters">Understanding and Applying Basic Display Filters</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-advanced-filtering-techniques">Advanced Filtering Techniques</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-analyzing-security-related-traffic">Analyzing Security-Related Traffic</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-analyzing-sample-traffic-and-generating-new-traffic">Analyzing Sample Traffic and Generating New Traffic</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before we start, you'll need to know <strong>Linux Basic Syntax.</strong> You can learn it through this <a target="_blank" href="https://labex.io/skilltrees/linux">Linux Skill Tree</a>.</p>
<p>Don't worry if you're new to <a target="_blank" href="https://labex.io/skilltrees/wireshark"><strong>Wireshark</strong></a> – I’ll explain everything as we go.</p>
<h2 id="heading-how-to-start-wireshark-and-analyze-network-traffic"><strong>How to Start Wireshark and Analyze Network Traffic</strong></h2>
<p>In this step, we're going to start using Wireshark. First, you'll learn how to launch it. Then, you'll either capture network traffic or use a provided sample file for analysis. Understanding the Wireshark interface is crucial, as it helps you view and analyze packet data.</p>
<h3 id="heading-installing-wireshark-on-ubuntu-2204">Installing Wireshark on Ubuntu 22.04</h3>
<p>Before you can start using Wireshark, you need to install it. Open a terminal window and run the following commands:</p>
<pre><code class="lang-bash">sudo apt update
sudo apt install wireshark -y
</code></pre>
<h3 id="heading-launching-wireshark"><strong>Launching Wireshark</strong></h3>
<p>To start Wireshark, you need to open a terminal window. You can do this by clicking on the terminal icon in the taskbar or by pressing <code>Ctrl+Alt+T</code>. Once the terminal is open, you'll use a command to start Wireshark. In the terminal, type the following command and press Enter:</p>
<pre><code class="lang-bash">wireshark
</code></pre>
<p>This command tells your system to start the Wireshark application. After a few seconds, Wireshark will open. You should see a window similar to the one shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385586635/78f76c20-c8d0-48d2-bdb7-17ff3f5fc261.png" alt="Wireshark Main Interface Example" class="image--center mx-auto" width="1666" height="678" loading="lazy"></p>
<h2 id="heading-how-to-work-with-network-capture-files"><strong>How to Work with Network Capture Files</strong></h2>
<p>For this part of the tutorial, you have two options:</p>
<h3 id="heading-option-1-use-the-provided-sample-file"><strong>Option 1: Use the Provided Sample File</strong></h3>
<pre><code class="lang-bash"><span class="hljs-comment"># Download a sample packet capture file with mixed traffic</span>
wget -q https://s3.amazonaws.com/tcpreplay-pcap-files/smallFlows.pcap -O /home/labex/project/sample.pcapng

<span class="hljs-comment"># Make sure the user has access to the file</span>
chmod 644 /home/labex/project/sample.pcapng
</code></pre>
<p>I’ve prepared a sample capture file for you at <code>/home/labex/project/sample.pcapng</code>. This file contains a variety of network traffic that you can analyze.</p>
<p>To open this file:</p>
<ol>
<li><p>In Wireshark, go to File &gt; Open</p>
</li>
<li><p>Navigate to <code>/home/labex/project/sample.pcapng</code></p>
</li>
<li><p>Click "Open"</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385612148/dbeb3d39-db15-4363-a499-e8b527b43d84.png" alt="Wireshark Open File Screenshot" class="image--center mx-auto" width="2606" height="2036" loading="lazy"></p>
<p>The file will load in Wireshark, showing various packets that have been captured previously.</p>
<h3 id="heading-option-2-capture-your-own-traffic"><strong>Option 2: Capture Your Own Traffic</strong></h3>
<p>If you prefer to capture your own traffic:</p>
<ol>
<li><p>In the Wireshark main window, look for the list of available network interfaces.</p>
</li>
<li><p>Find the <code>eth1</code> interface. In this lab environment, <code>eth1</code> is the main network interface we'll use for capturing packets.</p>
</li>
<li><p>Double-click on <code>eth1</code>. This action immediately starts the packet capture process.</p>
</li>
<li><p>Generate some network traffic by opening a new terminal and running:</p>
<pre><code class="lang-bash"> curl www.google.com
</code></pre>
</li>
<li><p>Once you've captured enough packets (aim for at least 20-30 packets), click the red square "Stop" button in the Wireshark toolbar.</p>
</li>
</ol>
<h2 id="heading-understanding-the-wireshark-interface"><strong>Understanding the Wireshark Interface</strong></h2>
<p>The Wireshark interface is divided into three main panels, each with a specific purpose:</p>
<ol>
<li><p><strong>Packet List (top panel)</strong>: This panel shows all the packets that have been captured in the order they were received. It gives you a quick overview of the captured traffic.</p>
</li>
<li><p><strong>Packet Details (middle panel)</strong>: When you select a packet in the top panel, this middle panel shows the details of that packet in a hierarchical format. It breaks down the packet's structure, showing information like the source and destination IP addresses, protocol types, and more.</p>
</li>
<li><p><strong>Packet Bytes (bottom panel)</strong>: This panel displays the raw bytes of the selected packet in hexadecimal format. It's useful for in-depth analysis, especially when you need to look at the exact data being transmitted.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743386808927/2225da6c-a652-4886-bd7d-f3c94586c688.jpeg" alt="Wireshark Interface" class="image--center mx-auto" width="1726" height="1312" loading="lazy"></p>
<p>To see how these panels work together, click on different packets in the top panel. You'll see the corresponding details and raw bytes update in the middle and bottom panels.</p>
<h2 id="heading-understanding-and-applying-basic-display-filters"><strong>Understanding and Applying Basic Display Filters</strong></h2>
<p>In this step, we're going to explore display filters in Wireshark. Display filters are essential tools when it comes to analyzing network traffic. They help you focus on specific types of packets instead of having to sift through all the captured data.</p>
<p>By the end of this section, you'll know what display filters are, why they're useful, and how to apply basic ones to isolate specific types of network traffic.</p>
<h3 id="heading-what-are-display-filters"><strong>What Are Display Filters?</strong></h3>
<p>When you're analyzing network traffic, looking at every single captured packet can be overwhelming. You usually want to focus on specific types of packets. That's where Wireshark display filters come in. They allow you to show only the packets that meet certain criteria. This makes the analysis process much more efficient because you're not wasting time on irrelevant data.</p>
<p>Display filters in Wireshark use a special syntax. This syntax enables you to filter packets based on various attributes such as protocols, IP addresses, ports, and even the content of the packets. Understanding this syntax is key to effectively using display filters.</p>
<h3 id="heading-filter-toolbar"><strong>Filter Toolbar</strong></h3>
<p>Take a look at the top of the Wireshark window. You'll notice a text field. It might be labeled "Apply a display filter..." or simply show "Expression...". This is the place where you'll enter your display filters. Once you enter a filter and press Enter, Wireshark will use that filter to show only the relevant packets.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385642595/018e9680-1c29-4168-9d60-975464722447.png" alt="Wireshark Filter Toolbar Location" class="image--center mx-auto" width="1666" height="634" loading="lazy"></p>
<h3 id="heading-basic-protocol-filters"><strong>Basic Protocol Filters</strong></h3>
<p>Let's start with a simple example. Suppose you want to view only HTTP traffic. HTTP is the protocol used for web browsing. To do this, you'll enter a filter in the filter toolbar. Type the following filter and then press Enter:</p>
<pre><code class="lang-plaintext">http
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385678124/1dff7e49-13c5-439e-aeca-82b461b8727b.png" alt="Wireshark HTTP Filter Output" class="image--center mx-auto" width="2602" height="1192" loading="lazy"></p>
<p>After you apply this filter, Wireshark will only display HTTP packets. All other packets will be temporarily hidden. You'll notice that the filter bar turns green when you apply a valid filter. This is a visual indication that your filter is working correctly.</p>
<p>The output should now show only packets related to HTTP traffic. This typically includes web requests (when you ask a website for information) and responses (when the website sends you the information). If you don't see any HTTP traffic in the sample file, you can try different protocols that might be present, such as TCP, UDP, or DNS:</p>
<pre><code class="lang-plaintext">tcp
</code></pre>
<p>Or try generating more HTTP traffic by running the <code>curl</code> command in a terminal:</p>
<pre><code class="lang-bash">curl www.google.com
</code></pre>
<h3 id="heading-ip-address-filters"><strong>IP Address Filters</strong></h3>
<p>Next, let's filter traffic based on IP addresses. An IP address is like a unique identifier for a device on a network. First, look at your packet list. You'll see columns labeled "Source" and "Destination". These columns show the IP addresses of the devices sending and receiving the packets.</p>
<p>Once you've identified an IP address that appears frequently in your capture (for example, let's say you see <code>192.168.1.1</code>), you can use it to create a filter. Type the following filter in the filter toolbar to see only packets from that source:</p>
<pre><code class="lang-plaintext">ip.src == 192.168.3.131
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385707141/8719b584-9498-4ecb-bf67-d354906626e0.png" alt="Wireshark IP Address Filter Example" class="image--center mx-auto" width="2602" height="1176" loading="lazy"></p>
<p>You can replace <code>192.168.3.131</code> with an IP address that you actually see in your capture. After applying this filter, only packets with that source IP address will be shown.</p>
<p>If you want to see all the packets again, you can clear the current filter. Just click the "Clear" button (X) on the right side of the filter bar.</p>
<h3 id="heading-port-filters"><strong>Port Filters</strong></h3>
<p>Many network services operate on specific ports. A port is like a door on a device that allows specific types of network traffic to enter or leave. For example, HTTP typically uses port 80.</p>
<p>To filter packets by port number, you can use the following filter:</p>
<pre><code class="lang-plaintext">tcp.port == 80
</code></pre>
<p>This filter will show both incoming and outgoing packets that use TCP port 80. You might also try other common ports like 443 (HTTPS) or 53 (DNS) depending on what's available in your capture.</p>
<h3 id="heading-combining-filters"><strong>Combining Filters</strong></h3>
<p>You can make your filters more powerful by combining them using logical operators like <code>and</code> and <code>or</code>. For example, if you want to show only HTTP traffic that uses port 80, you can use the following filter:</p>
<pre><code class="lang-plaintext">http and tcp.port == 80
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385736030/8230d965-e822-4341-afa5-35239fbb6975.png" alt="Example of combined filter in Wireshark" class="image--center mx-auto" width="2608" height="1156" loading="lazy"></p>
<p>Try applying different combinations of filters and observe how the displayed packets change. Remember, before trying a new filter, you can either clear the previous one by clicking the "Clear" button or modify the existing filter directly in the filter bar to build upon it.</p>
<h2 id="heading-advanced-filtering-techniques"><strong>Advanced Filtering Techniques</strong></h2>
<p>In this part, we'll explore how to create more sophisticated filters for detailed network traffic analysis. As a beginner, you might wonder why we need advanced filtering. Well, in real-world scenarios, network capture files can be extremely large, filled with all kinds of traffic. Advanced filtering techniques are like a powerful magnifying glass for security professionals. They help us quickly pick out the suspicious or important traffic from the sea of data in these large capture files.</p>
<h3 id="heading-complex-filters-with-multiple-conditions"><strong>Complex Filters with Multiple Conditions</strong></h3>
<p>Wireshark gives you the ability to build complex filters by combining multiple conditions. This is very useful when you want to be more precise in your traffic analysis. Let's start by creating a filter to find HTTP GET requests.</p>
<pre><code class="lang-plaintext">http.request.method == "GET"
</code></pre>
<p>This filter is designed to display only HTTP packets that contain GET requests. When you apply this filter, you'll see packets that are requests sent to web servers. The reason we use this filter is that GET requests are a common type of HTTP request used to retrieve data from a server. By isolating these requests, we can focus on the data retrieval activities in the network.</p>
<p>If your sample file doesn't contain HTTP GET requests, try this alternative filter to find TCP SYN packets which indicate connection attempts:</p>
<pre><code class="lang-plaintext">tcp.flags.syn == 1
</code></pre>
<p>Now, let's make our filter more specific. We'll add a port condition:</p>
<pre><code class="lang-plaintext">tcp.port == 80 and http.request.method == "GET"
</code></pre>
<p>This new filter shows only HTTP GET requests that occur on the standard HTTP port (80). The standard HTTP port is widely used for unencrypted web traffic. By adding this port condition, we're narrowing down our search to only those GET requests that are using the typical HTTP communication channel.</p>
<h3 id="heading-filtering-based-on-packet-size"><strong>Filtering Based on Packet Size</strong></h3>
<p>Network attacks often involve packets with unusual sizes. Attackers might use large or small packets to hide malicious data or to disrupt the normal functioning of the network. To filter based on packet size, we use a specific syntax:</p>
<pre><code class="lang-plaintext">tcp.len &gt;= 100 and tcp.len &lt;= 500
</code></pre>
<p>This filter displays TCP packets with a payload length between 100 and 500 bytes. You can adjust these values according to your needs. For example, if you suspect that an attack involves larger packets, you can increase the upper limit. By filtering based on packet size, we can identify abnormal traffic patterns that might indicate an attack.</p>
<h3 id="heading-filtering-based-on-specific-content"><strong>Filtering Based on Specific Content</strong></h3>
<p>You can also filter traffic based on specific content within packets. This is very useful when you're looking for traffic related to a particular website or service. For example, let's find HTTP traffic related to a specific website.</p>
<pre><code class="lang-plaintext">http.host contains "google"
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385773497/36b7bc2e-b7e9-4b68-9dc7-82e429c5ea01.png" alt="Wireshark HTTP Host Filter" class="image--center mx-auto" width="2618" height="1168" loading="lazy"></p>
<p>This filter shows only HTTP traffic where the host header contains "google". You can replace "google" with any domain you're interested in analyzing. The host header in an HTTP request tells the server which website the client is trying to access. By filtering based on the host header, we can focus on the traffic related to a specific domain.</p>
<p>If your sample file doesn't have HTTP traffic with host headers, try this more general content filter:</p>
<pre><code class="lang-plaintext">frame contains "http"
</code></pre>
<h3 id="heading-using-the-contains-operator-for-text-searching"><strong>Using the "contains" Operator for Text Searching</strong></h3>
<p>The <code>contains</code> operator is a handy tool for searching for specific text strings in packets. It allows us to look for certain keywords within the packet data.</p>
<pre><code class="lang-plaintext">frame contains "password"
</code></pre>
<p>This filter shows packets containing the word "password" anywhere in the packet data. This can be very helpful for detecting possible security issues. For example, if passwords are being sent in clear text (which is a big security risk), this filter can help us spot those packets.</p>
<p>Or try this filter:</p>
<pre><code class="lang-plaintext">frame contains "login"
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385793822/024b4482-0b5d-4b20-985c-6263bd7f48d6.png" alt="Wireshark Password Filter Example" class="image--center mx-auto" width="2612" height="1164" loading="lazy"></p>
<h3 id="heading-negating-filters"><strong>Negating Filters</strong></h3>
<p>Sometimes, you might want to see all the traffic except for certain types. That's where the <code>not</code> operator comes in.</p>
<pre><code class="lang-plaintext">not arp
</code></pre>
<p>This filter hides all ARP packets. ARP (Address Resolution Protocol) is used to map IP addresses to MAC addresses in a local network. Sometimes, ARP traffic can be very common and might clutter your analysis. By using the <code>not</code> operator, you can exclude this type of traffic and focus on other more relevant packets.</p>
<h3 id="heading-saving-and-applying-filter-bookmarks"><strong>Saving and Applying Filter Bookmarks</strong></h3>
<p>If you find yourself using certain filters frequently, you don't have to type them in every time. You can save them as bookmarks. Here's how:</p>
<ol>
<li><p>Enter a filter in the filter bar. This is where you type in the filter expressions we've been learning about.</p>
</li>
<li><p>Click the "+" button on the right side of the filter bar. This button is used to save the current filter as a bookmark.</p>
</li>
<li><p>Give your filter a name and click "OK". Naming the filter makes it easy to identify later.</p>
</li>
</ol>
<p>Once you've saved your filter, you can apply it by clicking on its name in the filter dropdown menu. This saves you time and effort, especially when you're doing repeated analysis.</p>
<h3 id="heading-exporting-filtered-packets"><strong>Exporting Filtered Packets</strong></h3>
<p>After you've filtered your traffic to show only the packets of interest, you might want to save just these packets to a new file. This is useful for sharing specific findings with colleagues or for further analysis. Here's how you do it:</p>
<ol>
<li><p>Apply your desired filter. Make sure you've set up the filter to show only the packets you want to save.</p>
</li>
<li><p>Click on File &gt; Export Specified Packets. This option allows you to export a specific set of packets.</p>
</li>
<li><p>Make sure "Displayed" is selected in the Packet Range section. This ensures that only the packets that are currently visible (that is, the ones that match your filter) are exported.</p>
</li>
<li><p>Choose a filename and location. This is where you decide where to save the new capture file and what to name it.</p>
</li>
<li><p>Click "Save". This creates a new capture file containing only the packets that matched your filter.</p>
</li>
</ol>
<h2 id="heading-analyzing-security-related-traffic"><strong>Analyzing Security-Related Traffic</strong></h2>
<p>In this step, we're going to focus on using Wireshark filters for security analysis. Security analysis is crucial in the world of cybersecurity as it helps us spot potentially malicious activities in network traffic. By the end of this section, you'll be able to identify various types of security threats using specific Wireshark filters.</p>
<h3 id="heading-identifying-port-scanning-activities"><strong>Identifying Port Scanning Activities</strong></h3>
<p>Port scanning is a common technique used by attackers to gather information about a target system. Attackers use it to find open ports on a network, which they can then exploit.</p>
<p>To detect potential port scanning, we look for a large number of connection attempts from a single source to multiple ports.</p>
<p>Let's use a specific filter to identify such activities. Try this filter in Wireshark:</p>
<pre><code class="lang-plaintext">tcp.flags.syn == 1 and tcp.flags.ack == 0
</code></pre>
<p>This filter shows SYN packets without the ACK flag. In a TCP connection, the SYN packet is the first one sent to initiate a connection, and the ACK packet is used to acknowledge the connection. When we see a lot of SYN packets without ACK from one source to different destination ports, it's a strong indication of port scanning.</p>
<h3 id="heading-detecting-suspicious-dns-traffic"><strong>Detecting Suspicious DNS Traffic</strong></h3>
<p>DNS tunneling and other DNS-based attacks are becoming more common. These attacks use the DNS protocol to hide malicious activities, such as data exfiltration or command and control communication. To detect such attacks, we need to look for unusual DNS traffic.</p>
<p>Use this filter to examine DNS queries:</p>
<pre><code class="lang-plaintext">dns
</code></pre>
<p>Once you apply this filter, look for unusually long domain names or a high volume of DNS requests to the same domain. These could be signs of data exfiltration or command and control communication.</p>
<h3 id="heading-identifying-password-brute-force-attempts"><strong>Identifying Password Brute Force Attempts</strong></h3>
<p>Password brute force attacks are a common way for attackers to gain unauthorized access to services like SSH or FTP. In a brute force attack, the attacker tries multiple password combinations until they find the correct one.</p>
<p>To detect potential brute force password attempts, we can filter for failed login attempts. Use this filter:</p>
<pre><code class="lang-plaintext">ftp contains "530" or ssh contains "Failed"
</code></pre>
<p>This filter shows FTP and SSH packets that contain common failure response messages. If you see multiple failures from the same source, it may indicate a brute force attempt.</p>
<h3 id="heading-analyzing-http-error-responses"><strong>Analyzing HTTP Error Responses</strong></h3>
<p>Web application attacks often generate HTTP error responses. Attackers may try to exploit vulnerabilities in web applications, and these attempts can result in error responses from the server.</p>
<p>Filter for these error responses with:</p>
<pre><code class="lang-plaintext">http.response.code &gt;= 400
</code></pre>
<p>This filter shows HTTP response packets with status codes of 400 or higher. All these status codes represent error responses. By examining these packets, we can identify attempted web exploits.</p>
<h3 id="heading-finding-clear-text-credentials"><strong>Finding Clear-Text Credentials</strong></h3>
<p>Transmitting credentials in clear text is a major security risk. If an attacker intercepts these credentials, they can gain unauthorized access to the system.</p>
<p>To detect clear-text credentials, use this filter:</p>
<pre><code class="lang-plaintext">http contains "user" or http contains "pass" or http contains "login"
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385832534/4c38654f-8ff0-4bc3-8bc6-0dd1161dc0f1.png" alt="Wireshark Clear-Text Cred Filter" class="image--center mx-auto" width="2620" height="1244" loading="lazy"></p>
<p>This filter helps us find HTTP traffic that might contain login information. Carefully examine the packets that match this filter to identify potential security risks.</p>
<h2 id="heading-analyzing-sample-traffic-and-generating-new-traffic"><strong>Analyzing Sample Traffic and Generating New Traffic</strong></h2>
<p>Now that you've learned various security-focused filters, it's time to put your knowledge into practice. You can either analyze the provided sample file or generate and analyze new traffic.</p>
<h3 id="heading-analyzing-the-sample-file"><strong>Analyzing the Sample File</strong></h3>
<p>If you're using the provided sample file (<code>/home/labex/project/sample.pcapng</code>), try applying some of the security filters we've discussed to identify any interesting patterns:</p>
<pre><code class="lang-plaintext">tcp.flags.syn == 1 and tcp.flags.ack == 0
</code></pre>
<p>Look for patterns that might indicate scanning, suspicious connections, or other security concerns.</p>
<h3 id="heading-generating-and-analyzing-new-traffic"><strong>Generating and Analyzing New Traffic</strong></h3>
<p>Alternatively, open a new terminal window. In this window, we'll generate some HTTP traffic with multiple requests. Run the following commands:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> {1..5}; <span class="hljs-keyword">do</span>
  curl -I www.google.com
  sleep 1
<span class="hljs-keyword">done</span>
</code></pre>
<p>These commands send five HTTP HEAD requests to <code>www.google.com</code> with a one-second interval between each request.</p>
<p>Next, go to Wireshark and apply this filter to find all HTTP requests:</p>
<pre><code class="lang-plaintext">http.request
</code></pre>
<p>This filter will show all the HTTP requests in the captured traffic.</p>
<p>Look through these packets to identify patterns of normal HTTP traffic. Notice the headers, the frequency of requests, and other details.</p>
<p>Finally, try to create a filter that can distinguish normal HTTP browsing from automated scanning tools. For example:</p>
<pre><code class="lang-plaintext">http.request and !(http.user_agent contains "Mozilla")
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1743385858895/3feb916b-39ac-4ced-ab76-8597186cbbf0.png" alt="Wireshark HTTP User Agent Filter" class="image--center mx-auto" width="2610" height="1184" loading="lazy"></p>
<p>This filter shows HTTP requests that don't have browser user agents. Since most normal web browsing is done using browsers with Mozilla in the user agent, requests without it might indicate automated tools rather than normal browsing.</p>
<p>By practicing these security-focused filtering techniques, you'll develop the skills needed to quickly identify suspicious traffic in real-world network captures.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this tutorial, you have learned how to use Wireshark display filters for network traffic analysis and potential security threat identification.</p>
<p>You began by either working with a provided sample capture file or capturing live network traffic and familiarizing yourself with the Wireshark interface. Then, you mastered basic display filters to isolate specific traffic types according to protocols, IP addresses, and ports. You also advanced your skills with complex filtering techniques, combining multiple conditions and searching for specific content. Finally, you applied these skills in security analysis scenarios to detect suspicious activities such as port scanning, credential exposure, and potential attacks.</p>
<p>These Wireshark filtering skills are crucial for efficient network troubleshooting and security analysis. By quickly isolating relevant packets from large captures, you can greatly reduce the time required to identify and respond to network issues and security incidents.</p>
<p>As you keep practicing with Wireshark, you will gain an intuitive understanding of network protocols and traffic patterns, enhancing your overall cybersecurity capabilities.</p>
<blockquote>
<p>To practice the operations from this tutorial, try the interactive hands-on lab: <a target="_blank" href="https://labex.io/labs/wireshark-analyze-network-traffic-with-wireshark-display-filters-415944?course=quick-start-with-wireshark">Analyze Network Traffic with Wireshark Display Filters</a></p>
</blockquote>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Simple Secure Chat System Using Netcat ]]>
                </title>
                <description>
                    <![CDATA[ In this hands-on tutorial, you'll learn how to harness the power of Netcat to build practical networking tools. We’ll start with basic message transmission. Then you'll progress to creating a file transfer system, and you’ll ultimately develop a secu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-simple-secure-chat-system-with-netcat/</link>
                <guid isPermaLink="false">671a491036e11cfa5033debb</guid>
                
                    <category>
                        <![CDATA[ cybersecurity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Netcat ]]>
                    </category>
                
                    <category>
                        <![CDATA[ shell ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Ubuntu ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Hang Hu ]]>
                </dc:creator>
                <pubDate>Thu, 24 Oct 2024 13:18:08 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729729356682/acf8ca42-3aaa-4ca1-9ebc-10f0f658c678.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this hands-on tutorial, you'll learn how to harness the power of Netcat to build practical networking tools.</p>
<p>We’ll start with basic message transmission. Then you'll progress to creating a file transfer system, and you’ll ultimately develop a secure chat application with encryption.</p>
<p>Here’s what we’ll cover:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-install-netcat">Install Netcat</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-your-first-network-connection">Your First Network Connection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-simple-file-transfer-tool">How to Build a Simple File Transfer Tool</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-secure-chat-system">How to Create a Secure Chat System</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-practice-your-skills">Practice Your Skills</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we start, you'll need:</p>
<ul>
<li><p>A Linux-based system: I recommend Ubuntu. Alternatively, you can use the <a target="_blank" href="https://labex.io/tutorials/linux-online-linux-playground-372915">Online Linux Terminal</a> if you don't have Linux installed.</p>
</li>
<li><p>Basic terminal knowledge (how to use <code>cd</code> and <code>ls</code>)</p>
</li>
</ul>
<p>Don't worry if you're new to networking - I’ll explain everything as we go!</p>
<h2 id="heading-install-netcat"><strong>Install Netcat</strong></h2>
<p><a target="_blank" href="https://nc110.sourceforge.io/">Netcat</a> is like a digital "pipe" between computers – anything you put in one end comes out the other. Before we start using it, let's get it installed on your system.</p>
<p>Open your terminal and run these commands:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Update your system's package list</span>
sudo apt update

<span class="hljs-comment"># Install Netcat</span>
sudo apt install netcat -y
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729583277378/d5fb06c5-3163-4885-b163-2cdde4fa434b.png" alt="Update your system's package list" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<p>To check if the installation worked, run:</p>
<pre><code class="lang-bash">nc -h
</code></pre>
<p>You should see a message starting with "OpenBSD netcat". If you do, great! If not, try running the installation commands again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729583329155/812f32b9-2ca7-41f6-aead-07ffacbf161c.png" alt="check if the installation worked" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<h2 id="heading-your-first-network-connection"><strong>Your First Network Connection</strong></h2>
<p>Before we dive into building tools, let's understand what a network connection actually is. Think of it like a phone call: one person needs to wait for the call (the listener), and another person needs to make the call (the connector).</p>
<p>In networking, we use "ports" to make these connections. You can think of ports like different phone lines – they let multiple conversations happen at the same time.</p>
<p>Let's try making our first connection:</p>
<ol>
<li>Open a terminal window and create a listener:</li>
</ol>
<pre><code class="lang-bash">nc -l 12345
</code></pre>
<p>What did we just do? The <code>-l</code> tells Netcat to "listen" for a connection, and <code>12345</code> is the port number we chose. Your terminal will look like it's frozen – that's normal! It's waiting for someone to connect.</p>
<ol start="2">
<li>Open another terminal window and connect to your listener:</li>
</ol>
<pre><code class="lang-bash">nc localhost 12345
</code></pre>
<p>Here, <code>localhost</code> means "this computer" – we're connecting to ourselves for practice. If you want to connect to another computer, you can replace <code>localhost</code> with its IP address.</p>
<p>Now try typing a message (like "hi") in either window and press Enter. Cool, right? The message appears in the other window! This is exactly how basic network communication works.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729583496294/da70a4bc-5626-493c-8a52-385b708593f4.png" alt="making our first connection" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<p>To stop the connection, press <code>Ctrl+C</code> in both windows.</p>
<h3 id="heading-what-just-happened"><strong>What Just Happened?</strong></h3>
<p>You just created your first network connection! The first terminal was like someone waiting by a phone, and the second terminal was like someone calling that phone. When they connected, they could send messages back and forth.</p>
<h2 id="heading-how-to-build-a-simple-file-transfer-tool"><strong>How to Build a Simple File Transfer Tool</strong></h2>
<p>Now that we understand basic connections, let's build something more useful: a tool to transfer files between computers.</p>
<p>First, let's create a test file to send:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create a file with some content</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"This is my secret message"</span> &gt; secret.txt
</code></pre>
<p>To transfer this file, we'll need two terminals again, but this time we'll use them differently:</p>
<ol>
<li>In the first terminal, set up the receiver:</li>
</ol>
<pre><code class="lang-bash">nc -l 12345 &gt; received_file.txt
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729583969994/d3159a2f-37f7-4cab-a23b-3788ed85876f.png" alt="transfer file" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<p>This tells Netcat to:</p>
<ul>
<li><p>Listen for a connection (<code>-l</code>)</p>
</li>
<li><p>Save whatever it receives to a file called <code>received_file.txt</code> (<code>&gt;</code>)</p>
</li>
</ul>
<ol start="2">
<li>In the second terminal, send the file:</li>
</ol>
<pre><code class="lang-bash">nc localhost 12345 &lt; secret.txt
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729583998676/ab865ded-626a-47aa-9df6-83e56aa5f5d1.png" alt="send the file" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<p>The <code>&lt;</code> tells Netcat to send the contents of our file.</p>
<ol start="3">
<li>Press Ctrl+C in both terminals to stop the transfer. Then check if it worked:</li>
</ol>
<pre><code class="lang-bash">cat received_file.txt
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729584030360/32fa9916-ffdb-49da-abcf-57569c9b2f79.png" alt="received file" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<p>You should see your message!</p>
<p>This is similar to our chat system, but instead of typing messages, we're:</p>
<ol>
<li><p>Taking content from a file</p>
</li>
<li><p>Sending it through our network connection</p>
</li>
<li><p>Saving it to a new file on the other end</p>
</li>
</ol>
<p>Think of it like sending a document through a fax machine!</p>
<h2 id="heading-how-to-create-a-secure-chat-system"><strong>How to Create a Secure Chat System</strong></h2>
<p>Our previous examples sent everything as plain text – anyone could read it if they intercepted the connection. Let's make something more secure by adding encryption.</p>
<p>First, let's understand what encryption does:</p>
<ul>
<li><p>It's like putting your message in a locked box</p>
</li>
<li><p>Only someone with the right key can open it</p>
</li>
<li><p>Even if someone sees the box, they can't read your message</p>
</li>
</ul>
<p>We'll create two scripts: one for sending messages and one for receiving them.</p>
<ol>
<li>Create the sender script:</li>
</ol>
<pre><code class="lang-bash">nano secure_sender.sh
</code></pre>
<p>Copy this code into the file:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">"Secure Chat - Type your messages below"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Press Ctrl+C to exit"</span>

<span class="hljs-keyword">while</span> <span class="hljs-literal">true</span>; <span class="hljs-keyword">do</span>
  <span class="hljs-comment"># Get the message</span>
  <span class="hljs-built_in">read</span> message

  <span class="hljs-comment"># Encrypt and send it</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$message</span>"</span> | openssl enc -aes-256-cbc -salt -base64 \
    -pbkdf2 -pass pass:chatpassword 2&gt;/dev/null | \
    nc -N localhost 12345
<span class="hljs-keyword">done</span>
</code></pre>
<p>This script will:</p>
<ol>
<li><p>Read messages from user input.</p>
</li>
<li><p>Encrypt them using OpenSSL's AES-256-CBC encryption (a strong encryption standard).</p>
</li>
<li><p>Send the encrypted message to the specified port.</p>
</li>
</ol>
<p>Press Ctrl+X, then Y, then Enter to save.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729584825701/bcd3c3fb-5cd5-40f7-8105-14d1fff069ec.png" alt="Create the sender script" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<ol start="2">
<li>Create the receiver script:</li>
</ol>
<pre><code class="lang-bash">nano secure_receiver.sh
</code></pre>
<p>Copy this code:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">"Waiting for messages..."</span>

<span class="hljs-keyword">while</span> <span class="hljs-literal">true</span>; <span class="hljs-keyword">do</span>
  <span class="hljs-comment"># Receive and decrypt messages</span>
  nc -l 12345 | openssl enc -aes-256-cbc -d -salt -base64 \
    -pbkdf2 -pass pass:chatpassword 2&gt;/dev/null
<span class="hljs-keyword">done</span>
</code></pre>
<p>This script will:</p>
<ol>
<li><p>Listen for incoming encrypted messages.</p>
</li>
<li><p>Decrypt them using the same encryption key.</p>
</li>
<li><p>Display the decrypted messages.</p>
</li>
</ol>
<p>Save this file too.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729584787785/c1e329ad-cbbe-49e8-918f-25d683884972.png" alt="Create the receiver script" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<ol start="3">
<li>Make both scripts executable:</li>
</ol>
<pre><code class="lang-bash">chmod +x secure_sender.sh secure_receiver.sh
</code></pre>
<ol start="4">
<li>Try it out:</li>
</ol>
<ul>
<li><p>In one terminal: <code>./secure_receiver.sh</code></p>
</li>
<li><p>In another terminal: <code>./secure_sender.sh</code></p>
</li>
</ul>
<p>Type a message in the sender terminal. The receiver will show your decrypted message!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729584834464/1f902a94-3a79-404b-bc9f-af9d8d2471e0.png" alt="Type a message in the sender terminal" class="image--center mx-auto" width="1920" height="1440" loading="lazy"></p>
<h3 id="heading-enhancing-our-chat-system"><strong>Enhancing Our Chat System</strong></h3>
<p>Now that we have a working basic chat system, let's make it more user-friendly and informative. We'll add features like timestamps, color-coded messages, and encryption status updates. This enhanced version will help you better understand what's happening during the encryption and transmission process.</p>
<p>If you're comfortable with the basic version, try this improved version:</p>
<ol>
<li>Create an enhanced sender script (save it as <code>secure_sender_v2.sh</code>):</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment"># Set up color codes for better visibility</span>
GREEN=<span class="hljs-string">'\033[0;32m'</span>
BLUE=<span class="hljs-string">'\033[0;34m'</span>
NC=<span class="hljs-string">'\033[0m'</span> <span class="hljs-comment"># No Color</span>

<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>Secure Chat Sender - Started at <span class="hljs-subst">$(date)</span><span class="hljs-variable">${NC}</span>"</span>
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>Type your messages below. Press Ctrl+C to exit<span class="hljs-variable">${NC}</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"----------------------------------------"</span>

<span class="hljs-keyword">while</span> <span class="hljs-literal">true</span>; <span class="hljs-keyword">do</span>
    <span class="hljs-comment"># Show prompt with timestamp</span>
    <span class="hljs-built_in">echo</span> -ne <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>[<span class="hljs-subst">$(date +%H:%M:%S)</span>]<span class="hljs-variable">${NC}</span> Your message: "</span>

    <span class="hljs-comment"># Get the message</span>
    <span class="hljs-built_in">read</span> message

    <span class="hljs-comment"># Skip if message is empty</span>
    <span class="hljs-keyword">if</span> [ -z <span class="hljs-string">"<span class="hljs-variable">$message</span>"</span> ]; <span class="hljs-keyword">then</span>
        <span class="hljs-built_in">continue</span>
    <span class="hljs-keyword">fi</span>

    <span class="hljs-comment"># Add timestamp to message</span>
    timestamped_message=<span class="hljs-string">"[<span class="hljs-subst">$(date +%H:%M:%S)</span>] <span class="hljs-variable">$message</span>"</span>

    <span class="hljs-comment"># Show encryption status</span>
    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>Encrypting and sending message...<span class="hljs-variable">${NC}</span>"</span>

    <span class="hljs-comment"># Encrypt and send it, showing the encrypted form</span>
    encrypted=$(<span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$timestamped_message</span>"</span> | openssl enc -aes-256-cbc -salt -base64 \
        -pbkdf2 -iter 10000 -pass pass:chatpassword 2&gt;/dev/null)

    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>Encrypted form:<span class="hljs-variable">${NC}</span> <span class="hljs-variable">${encrypted:0:50}</span>..."</span> <span class="hljs-comment"># Show first 50 chars</span>
    <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$encrypted</span>"</span> | nc -N localhost 12345

    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>Message sent successfully!<span class="hljs-variable">${NC}</span>"</span>
    <span class="hljs-built_in">echo</span> <span class="hljs-string">"----------------------------------------"</span>
<span class="hljs-keyword">done</span>
</code></pre>
<ol start="2">
<li>Create an enhanced receiver script (save as <code>secure_receiver_v2.sh</code>):</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment"># Set up color codes for better visibility</span>
GREEN=<span class="hljs-string">'\033[0;32m'</span>
BLUE=<span class="hljs-string">'\033[0;34m'</span>
YELLOW=<span class="hljs-string">'\033[1;33m'</span>
NC=<span class="hljs-string">'\033[0m'</span> <span class="hljs-comment"># No Color</span>

<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>Secure Chat Receiver - Started at <span class="hljs-subst">$(date)</span><span class="hljs-variable">${NC}</span>"</span>
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>Waiting for messages... Press Ctrl+C to exit<span class="hljs-variable">${NC}</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"----------------------------------------"</span>

<span class="hljs-keyword">while</span> <span class="hljs-literal">true</span>; <span class="hljs-keyword">do</span>
    <span class="hljs-comment"># Receive and show the encrypted message</span>
    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>Waiting for next message...<span class="hljs-variable">${NC}</span>"</span>

    encrypted=$(nc -l 12345)

    <span class="hljs-comment"># Skip if received nothing</span>
    <span class="hljs-keyword">if</span> [ -z <span class="hljs-string">"<span class="hljs-variable">$encrypted</span>"</span> ]; <span class="hljs-keyword">then</span>
        <span class="hljs-built_in">continue</span>
    <span class="hljs-keyword">fi</span>

    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${YELLOW}</span>Received encrypted message:<span class="hljs-variable">${NC}</span> <span class="hljs-variable">${encrypted:0:50}</span>..."</span> <span class="hljs-comment"># Show first 50 chars</span>
    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>Decrypting...<span class="hljs-variable">${NC}</span>"</span>

    <span class="hljs-comment"># Decrypt and display the message</span>
    decrypted=$(<span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$encrypted</span>"</span> | openssl enc -aes-256-cbc -d -salt -base64 \
        -pbkdf2 -iter 10000 -pass pass:chatpassword 2&gt;/dev/null)

    <span class="hljs-comment"># Check if decryption was successful</span>
    <span class="hljs-keyword">if</span> [ $? -eq 0 ]; <span class="hljs-keyword">then</span>
        <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>Decrypted message:<span class="hljs-variable">${NC}</span> <span class="hljs-variable">$decrypted</span>"</span>
    <span class="hljs-keyword">else</span>
        <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"\033[0;31mError: Failed to decrypt message<span class="hljs-variable">${NC}</span>"</span>
    <span class="hljs-keyword">fi</span>

    <span class="hljs-built_in">echo</span> <span class="hljs-string">"----------------------------------------"</span>
<span class="hljs-keyword">done</span>
</code></pre>
<ol start="3">
<li>Make the enhanced scripts executable:</li>
</ol>
<pre><code class="lang-bash">chmod +x secure_sender_v2.sh secure_receiver_v2.sh
</code></pre>
<p>Try running both versions to see how the additional feedback helps you better understand the encryption and communication process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729585592733/01d25154-37a9-4c14-95ac-410c513956b9.png" alt="Enhancing Our Chat System" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<p>The enhanced version (v2) adds several improvements:</p>
<ul>
<li><p>Colorized output for better readability.</p>
</li>
<li><p>Timestamps for each message.</p>
</li>
<li><p>Status updates showing the encryption/decryption process.</p>
</li>
<li><p>Error handling for failed decryption attempts.</p>
</li>
<li><p>Preview of encrypted messages before sending/after receiving.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This tutorial taught you how to use Netcat as a versatile networking tool. We started with basic message sending, progressed to building a simple file transfer system, and then created a secure chat system with encryption.</p>
<p>You've gained hands-on experience with:</p>
<ul>
<li><p>Setting up network listeners and connections</p>
</li>
<li><p>Transferring files securely between systems</p>
</li>
<li><p>Implementing basic encryption for secure communication</p>
</li>
<li><p>Adding user-friendly features like timestamps and status updates</p>
</li>
</ul>
<p>The skills you've learned here form a solid foundation for understanding network communication and can be applied to more complex networking projects. To practice the operations from this tutorial, try <a target="_blank" href="https://labex.io/labs/linux-using-netcat-for-simple-network-communication-392039">the interactive hands-on lab</a>.</p>
<h2 id="heading-practice-your-skills"><strong>Practice Your Skills</strong></h2>
<p>Now that you've learned the basics of Netcat and built a secure chat system, let's put your skills to the test with a real-world scenario. Try the "<a target="_blank" href="https://labex.io/labs/linux-receive-messages-using-netcat-392102"><strong>Receive Messages Using Netcat</strong></a>" lab challenge where you'll play the role of a junior interstellar communications analyst. Your mission: intercept and log signals from an alien civilization using your newfound Netcat knowledge.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
