<?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>Forem: Filipe Câncio</title>
    <description>The latest articles on Forem by Filipe Câncio (@cancio).</description>
    <link>https://forem.com/cancio</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%2F329542%2Fb3e9c9fc-6ce8-44d7-a7aa-926def3dcd17.png</url>
      <title>Forem: Filipe Câncio</title>
      <link>https://forem.com/cancio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/cancio"/>
    <language>en</language>
    <item>
      <title>Resolvendo o desafio 509. Fibonacci Number</title>
      <dc:creator>Filipe Câncio</dc:creator>
      <pubDate>Sun, 23 Nov 2025 17:43:38 +0000</pubDate>
      <link>https://forem.com/cancio/resolvendo-o-desafio-509-fibonacci-number-5def</link>
      <guid>https://forem.com/cancio/resolvendo-o-desafio-509-fibonacci-number-5def</guid>
      <description>&lt;p&gt;&lt;a href="https://leetcode.com/problems/fibonacci-number/description/" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A lógica do fibonacci é bem simples. O número atual é resultado da soma do número anterior mais o seu anterior &lt;code&gt;(n-1)+(n-2)&lt;/code&gt;. Considerando apenas o conjunto dos números naturais, adicionamos uma regra para os números &lt;code&gt;0&lt;/code&gt; e &lt;code&gt;1&lt;/code&gt;, cujo os seus correspondentes são eles mesmos &lt;code&gt;f(0) = 0&lt;/code&gt; e &lt;code&gt;f(1)=1&lt;/code&gt; e assim temos a sequência &lt;code&gt;0 1 1 2 3 5 ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;podemos começar com então com a que representa a função matemática de Fibonacci &lt;code&gt;f(n) = f(n-1) = f(n-2)&lt;/code&gt;, a &lt;strong&gt;solução recursiva&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Solução recursiva
&lt;/h1&gt;

&lt;p&gt;Na solução recursiva vamos colocar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nosso caso base &lt;code&gt;n = 0&lt;/code&gt; e &lt;code&gt;n = 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;E a expressão matemática &lt;code&gt;f(n) = f(n-1) = f(n-2)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;p&gt;É uma solução simples e compreensiva, porém acredite não é a das melhores. &lt;/p&gt;

&lt;h2&gt;
  
  
  Complexity
&lt;/h2&gt;

&lt;p&gt;Vamos pensar em &lt;code&gt;fib(6)&lt;/code&gt;, e realizar um teste de mesa (não vou trocar &lt;code&gt;fib(1) e fib(0)&lt;/code&gt; por 1 e 0 no nosso teste de mesa porque não precisamos nos apegar ao valor mas ao número de instruções):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;th&gt;Recursão&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;th&gt;Intruções&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fib(6)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(5)&lt;/code&gt; + &lt;code&gt;fib(4)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(1) + fib(0) + fib(1) + fib(1) + fib(0) + fib(1) + fib(0) + fib(1)&lt;/code&gt; + &lt;code&gt;fib(1) + fib(0) + fib(1) + fib(1) + fib(0)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fib(5)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(4)&lt;/code&gt; + &lt;code&gt;fib(3)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(1) + fib(0) + fib(1) + fib(1) + fib(0)&lt;/code&gt; + &lt;code&gt;fib(1) + fib(0) + fib(1)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fib(4)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(3)&lt;/code&gt; + &lt;code&gt;fib(2)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(1) + fib(0) + fib(1)&lt;/code&gt; + &lt;code&gt;fib(1) + fib(0)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fib(3)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(2)&lt;/code&gt; + &lt;code&gt;fib(1)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(1) + fib(0)&lt;/code&gt; + &lt;code&gt;fib(1)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fib(2)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fib(1)&lt;/code&gt; + &lt;code&gt;fib(0)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Observando o resultado do nosso teste vemos algo assustador. Para exercutarmos essa função, nos a rodamos o &lt;strong&gt;número corresponte ao seu valor em finonacci&lt;/strong&gt;! Ou seja pensando na perspectiva de &lt;code&gt;f(x) = y&lt;/code&gt;da matemática, em um número &lt;code&gt;n&lt;/code&gt; de entradas levamos exatamente &lt;code&gt;y&lt;/code&gt; para retornar o próprio &lt;code&gt;y&lt;/code&gt;!&lt;br&gt;
Aproveitando a matemática, a &lt;code&gt;f(x) = y&lt;/code&gt;que corresponde à complexidade de Fibonacci é $\phi$ é o Número de Ouro ($\approx 1.618$). Ou seja a complexidade de tempo dessa função é $O(1.618^n)$ mas a gente arredonda para a complexidade assinstótica de $O(2^n)$.&lt;br&gt;
E quanto armazenamento? podemos ver no teste de mesa que nos igualamos as funções (&lt;code&gt;f(3)&lt;/code&gt; = &lt;code&gt;f(2)+f(1)&lt;/code&gt;), no fim o código recursivo acaba passando por todas as definições de &lt;code&gt;f(n)&lt;/code&gt; e igualando ao seu valor, ou seja, para cada &lt;code&gt;n&lt;/code&gt; valor temos salvo &lt;code&gt;n&lt;/code&gt; definições ocupando um espaço &lt;code&gt;n&lt;/code&gt; de memória.&lt;/p&gt;

&lt;p&gt;Em resumo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time complexity: $O(2^n)$&lt;/li&gt;
&lt;li&gt;Space complexity: $O(n)$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Existe um forma mais rápida de solucionar esse caso e é também simples. Muito parecida com o que nos usamos logo quando quando aprendermos fibonacci na escola.&lt;/p&gt;
&lt;h1&gt;
  
  
  Solução iterativa
&lt;/h1&gt;

&lt;p&gt;No ensino fundamental, quando a professora pedia para calcularmos o valor de de fibonacci de 20, somávamos a sequencia de valores 20 vezes até chegar o valor correspondente, correto? Nessa solução faremos o mesmo! Vamos iterar de 2 a n somando consecutivamente até chegarmos no nosso valor.&lt;br&gt;
Nesa solução iterativa vamos colocar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nosso caso base &lt;code&gt;n = 0&lt;/code&gt; e &lt;code&gt;n = 1&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Uma variável &lt;code&gt;i&lt;/code&gt; que começa com &lt;code&gt;2&lt;/code&gt; e incrementa até &lt;code&gt;n&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Duas variáveis, uma para salvar &lt;code&gt;i-1&lt;/code&gt; e outra &lt;code&gt;i-2&lt;/code&gt; no valor correspondente de &lt;code&gt;i&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Podemos falar que essas duas variáveis são dois ponteiros, são dois savepoints, onde eu vou deixar resgistrados valores que me importam. No fim da iteração eu apenas retorno o valor do primeiro ponteiro &lt;code&gt;i-1&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Porque?&lt;/p&gt;

&lt;p&gt;Bem durante a iteração, você vai:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Colocar o valor de &lt;code&gt;i-1&lt;/code&gt; em um ponteiro temporário, pode ser um &lt;code&gt;c&lt;/code&gt; (&lt;code&gt;i-1&lt;/code&gt; seria &lt;code&gt;a&lt;/code&gt; e &lt;code&gt;i-2&lt;/code&gt; seria &lt;code&gt;b&lt;/code&gt;),&lt;/li&gt;
&lt;li&gt;Somar esse dois ponteiros &lt;code&gt;i-1&lt;/code&gt; e &lt;code&gt;i-2&lt;/code&gt; e salvar em &lt;code&gt;i-1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Colocar o valor de &lt;code&gt;c&lt;/code&gt; em &lt;code&gt;i-2&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;c&lt;/code&gt; morre no fim de cada ciclo da iteração, ele so serve pra fazer a troca de valores depois da soma. No fim da iteração o valor em &lt;code&gt;i-1&lt;/code&gt; sempre irá corresponder ao &lt;code&gt;f(n)&lt;/code&gt; do próximo valor de &lt;code&gt;i&lt;/code&gt; e assim que acaba temos de fato &lt;code&gt;f(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;p&gt;Você pode ter olhado o código correspondente da sua linguagem e passado reto nas outras, mas se parar e olhar com calma, cada linguagem tem uma forma interessante de iterar os valores e de passar entre os ponteiros &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt; e &lt;code&gt;c&lt;/code&gt;. Na real, alguns nem tem o ponteiro &lt;code&gt;c&lt;/code&gt;, legal né?&lt;/p&gt;

&lt;p&gt;Uma característica que essas linguagens tem em comum é o swap, a capacidade de troca de valores entre variáveis. Vou deixar aqui uma listinha de possibilidade de swap entre linguagens.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Linguagem&lt;/th&gt;
&lt;th&gt;Atribuição de valores&lt;/th&gt;
&lt;th&gt;Troca de valores&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int a = 1; int b = 0;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a = (b += a) - a;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kotlin&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var (a, b) = 0 to 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var (a, b) = 1 to 0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swift&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var (a, b) = (0, 1)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(a, b) = (b, a + b)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dart&lt;/td&gt;
&lt;td&gt;&lt;code&gt;var (a, b) = (0, 1)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(a, b) = (b, a + b)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Essas sobreposições de valores causam um efeito significativo nessa versão do algoritmo de fibonacci, a solução em termos de espaço passa a ser $O(1)$, já a de tempo, $O(n)$. Porque? Bem, temos os seguintes pontos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nossos ponteiros sempre serão 3 (ou 2...). Na duvida, complexidade assintótica de $O(1)$,&lt;/li&gt;
&lt;li&gt;Temos um fluxo de iteração de 2 para n, ou seja executamos as instruções de soma n vezes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;assim em resumo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time complexity: $O(n)$&lt;/li&gt;
&lt;li&gt;Space complexity: $O(1)$&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bem, tudo que é bom, pode melhorar e por mais que um algoritmo $O(n)$ não seja péssimo, existe algumas soluções mais "velozes" em perpectiva de complexidade assintótica. No proximo algorítmo veremos como usar uma propriedade da algebra para resolver o problema de fibonacci, desta vez usaremos matrizes!&lt;/p&gt;

&lt;h1&gt;
  
  
  Solução com exponenciação de matrizes
&lt;/h1&gt;

</description>
      <category>leetcode</category>
      <category>algorithms</category>
      <category>kotlin</category>
      <category>java</category>
    </item>
    <item>
      <title>Exemplificando SOLID com Jetpack Compose - parte S</title>
      <dc:creator>Filipe Câncio</dc:creator>
      <pubDate>Thu, 10 Oct 2024 22:16:27 +0000</pubDate>
      <link>https://forem.com/cancio/exemplificando-solid-com-jetpack-compose-parte-s-3lde</link>
      <guid>https://forem.com/cancio/exemplificando-solid-com-jetpack-compose-parte-s-3lde</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Esta é uma nova série de artigos composta em cinco partes, uma para cada princípio do SOLID. Vou deixar o link para uma versão em inglês aqui, quando tiver uma, e vou deixar os artigos seguintes no final deste artigo quando forem feitos também.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Existem tópicos na área de desenvolvimento que são muito importantes de se aprender, e o SOLID é um deles. Às vezes encontramos situações em que não percebemos, à primeira vista, que podemos implementar esses princípios e que poderiam ser um ótimo exemplo de implementação no trabalho ou em uma entrevista de emprego. &lt;/p&gt;

&lt;p&gt;Nesta série de artigos, vamos usar os conceitos de SOLID com Jetpack Compose e ver casos onde essa tecnologia performa muito bem com os conceitos apresentados.&lt;/p&gt;

&lt;p&gt;O princípio que iremos focar aqui é o &lt;strong&gt;S - Single-responsibility principle (SRP) ou Princípio da Responsabilidade Única&lt;/strong&gt;, que dita que uma classe (no nosso caso, um composable) deve ter apenas uma única responsabilidade, ou seja, deve fazer uma única ação ou mudança.&lt;/p&gt;

&lt;p&gt;Em nosso exemplo, vamos analisar o caso de uma &lt;code&gt;HomeScreen&lt;/code&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%2F8mcuesnvf6uvl0e5kzid.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%2F8mcuesnvf6uvl0e5kzid.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em nossa &lt;code&gt;HomeScreen&lt;/code&gt;, o designer desenvolveu alguns fluxos na tela para dar comportamentos quando interagida com o usuário. A primeira coisa que acontece é o carregamento dos conteúdos; em seguida, caso o carregamento ocorra bem, é exibida uma lista de conteúdos. O designer acrescentou também alguns elementos na tela caso o carregamento não ocorra bem ou não tenha nenhum conteúdo.&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%2Fdh6njuwk551maomuqidv.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%2Fdh6njuwk551maomuqidv.png" alt="Image description" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em um desenvolvimento comum com &lt;code&gt;XML&lt;/code&gt;, é esperado que alguns elementos sejam criados em tela e ocultados. Durante a execução das &lt;code&gt;activities&lt;/code&gt;, decidimos quando eles devem aparecer. Por exemplo, se a tela tiver uma lista de conteúdos, o botão "new" deve ser pequeno e em formato de losango; quando não houver nenhum conteúdo, ele deve ser um retângulo comum e largo; caso o conteúdo esteja carregando, ele não deve aparecer.&lt;/p&gt;

&lt;p&gt;Para esse caso, pode ser uma implementação simples, mas sabemos que em uma tela com diversos comportamentos e casos de exceção isso pode se tornar um pesadelo de condicionais e, devido à complexidade, a cada mudança no código, um novo comportamento inesperado pode ocorrer.&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%2F4mibijdicsu8m6k572lm.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%2F4mibijdicsu8m6k572lm.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementando o Single-responsibility principle(SRP)
&lt;/h2&gt;

&lt;p&gt;No nosso exemplo, iremos dividir cada comportamento de tela em componentes, uma série de funções que definirão o fluxo exibido na tela. Se você já conhece o básico de Jetpack Compose, sabe que podemos criar uma view com uma simples função e a anotação &lt;code&gt;@Composable&lt;/code&gt;, então não vamos abordar isso aqui.&lt;/p&gt;

&lt;p&gt;Vamos definir cada responsabilidade por:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loading: carregando conteúdo&lt;/li&gt;
&lt;li&gt;Content: foi carregado uma lista de conteúdos&lt;/li&gt;
&lt;li&gt;Empty: foi carregado uma lista vazia&lt;/li&gt;
&lt;li&gt;Error: houve um erro no carregamento&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A solução seria simplesmente criarmos os componentes abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;HomeLoadingScreen&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.}&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;

&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;HomeContentScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;contentList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="n"&gt;onNewClick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.}&lt;/span&gt;

&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;HomeEmptyScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;onNewClick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.}&lt;/span&gt;

&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;HomeErrorScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;onOkClick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Unit&lt;/span&gt;
&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FIM&lt;/strong&gt; Brincadeira pessoal, apesar do uso do SRP já estar exposto, vamos dar um sentido para essa separação de responsabilidade, afinal, ainda não sabemos como pode ser útil. Primeiro precisamos entender que existe uma função &lt;code&gt;HomeScreen&lt;/code&gt; e que essas funções de comportamento serão renderizadas nela. E isso vai depender de uma mudança de estado. Além da &lt;code&gt;HomeScreen&lt;/code&gt;, temos a &lt;code&gt;HomeViewModel&lt;/code&gt; que vai criar nossa variável &lt;code&gt;MutableLiveData&lt;/code&gt; que vai ficar mutando durante o uso do app. &lt;/p&gt;

&lt;p&gt;O tipo do nosso &lt;code&gt;MutableLiveData&lt;/code&gt; será uma classe selada &lt;code&gt;HomeUIState&lt;/code&gt; que terá classes e objetos filhos representando cada comportamento (ou responsabilidade).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;HomeScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;HomeViewModel&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
   &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colectAsState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomeViewModel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="py"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;MutableLiveData&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;HomeUIState&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;

&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;


   &lt;span class="k"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomeUIState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;HomeUIState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="kd"&gt;data class&lt;/span&gt; &lt;span class="nc"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;contentList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;):&lt;/span&gt; &lt;span class="nc"&gt;HomeUIState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;HomeUIState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;HomeUIState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, vamos criar algumas funções que atualizem nosso estado &lt;code&gt;uiState&lt;/code&gt; (o &lt;code&gt;MutableLiveData&lt;/code&gt;). Funções que representam momentos como o carregamento de uma &lt;code&gt;API&lt;/code&gt;, ou uma coleta no &lt;code&gt;sharedPreferences&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomeViewModel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;ViewModel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onGetListSuccess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;//verify if is empty&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;
         &lt;span class="n"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onGetListFailure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por fim, as telas em &lt;code&gt;HomeScreen&lt;/code&gt; são renderizadas através de um &lt;code&gt;When&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Composable&lt;/span&gt;
&lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;HomeScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;HomeViewModel&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
   &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uiState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colectAsState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

   &lt;span class="k"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;Loading&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;HomeLoadingScreen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;HomeContentScreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contentList&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNewContent&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
      &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;Empty&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;HomeEmptyScreen&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNewContent&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
      &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;HomeErrorStreen&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadContents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em resumo, definimos uma única responsabilidade para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HomeLoadingScreen&lt;/code&gt;: exibir os componentes correspondentes quando a tela estiver carregando os conteúdos.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HomeContentScreen&lt;/code&gt;: exibir os componentes correspondentes quando a tela estiver com a lista de conteúdos.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HomeEmptyScreen&lt;/code&gt;: exibir os componentes correspondentes quando a tela estiver com a lista vazia.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HomeErrorScreen&lt;/code&gt;: exibir os componentes correspondentes quando tiver algum erro.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HomeScreen&lt;/code&gt;: gerenciar os estados recebidos e escolher o que exibir.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No próximo artigo, iremos observar os outros princípios do &lt;strong&gt;SOLID&lt;/strong&gt; usando &lt;strong&gt;Jetpack Compose&lt;/strong&gt;. Vou deixar a listinha aqui abaixo, na medida que os artigos forem criados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exemplificando SOLID com Jetpack Compose - parte S&lt;/li&gt;
&lt;li&gt;Exemplificando SOLID com Jetpack Compose - parte O&lt;/li&gt;
&lt;li&gt;Exemplificando SOLID com Jetpack Compose - parte L&lt;/li&gt;
&lt;li&gt;Exemplificando SOLID com Jetpack Compose - parte I&lt;/li&gt;
&lt;li&gt;Exemplificando SOLID com Jetpack Compose - parte D&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jetpackcompose</category>
      <category>kotlin</category>
      <category>android</category>
      <category>kmp</category>
    </item>
    <item>
      <title>Configurando firewall com Docker</title>
      <dc:creator>Filipe Câncio</dc:creator>
      <pubDate>Tue, 05 Dec 2023 16:04:16 +0000</pubDate>
      <link>https://forem.com/cancio/configurando-firewall-com-docker-4233</link>
      <guid>https://forem.com/cancio/configurando-firewall-com-docker-4233</guid>
      <description>&lt;p&gt;Neste post usaremos o iptables para configurar firewalls usando containers dockers.&lt;br&gt;
O iptables é uma ferramenta para configurar firewalls e Nat disponível para dispositivos linux. Dentre as variadas funcionalidades, iremos configurar aqui no projeto o acesso de um container docker com outro. Para isso, precisaremos duas imagens docker: a &lt;a href="https://hub.docker.com/r/filipecancio/kali-iptables" rel="noopener noreferrer"&gt;filipecancio/kali-iptables&lt;/a&gt; e a &lt;a href="https://hub.docker.com/r/filipecancio/server-iptables" rel="noopener noreferrer"&gt;filipecancio/server-iptables&lt;/a&gt;. Vamos fazer o pull das duas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull filipecancio/kali-iptables
docker pull filipecancio/server-iptables
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criaremos então um máquina com o nome &lt;code&gt;server&lt;/code&gt; com o server-iptables e outra &lt;code&gt;client&lt;/code&gt; com o kali linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Criando a maquina server&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--cap-add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NET_ADMIN &lt;span class="nt"&gt;--cap-add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NET_RAW &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;--name&lt;/span&gt; server filipecancio/server-iptables

&lt;span class="c"&gt;# Criando a maquina client&lt;/span&gt;
docker run &lt;span class="nt"&gt;--name&lt;/span&gt; client &lt;span class="nt"&gt;--cap-add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NET_ADMIN &lt;span class="nt"&gt;--cap-add&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NET_RAW &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; filipecancio/kali-iptables bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A máquina &lt;code&gt;server&lt;/code&gt; não foi executada automaticamente pelo bash pois ela é uma aplicação nodeJS rodando em uma máquina alpine, então usaremos o comando abaixo para acessá-lo (o mesmo comando pode ser usado para acessar o &lt;code&gt;client&lt;/code&gt; posteriormente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; root server sh

&lt;span class="c"&gt;# caso queira acessar novamente o client via bash&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; client /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note que usaremos a flag &lt;code&gt;--user root&lt;/code&gt; para poder fazer as alterações de root na maquina&lt;/p&gt;

&lt;p&gt;Se você usar o navegador com endereço &lt;code&gt;localhost:8080&lt;/code&gt; poderá ver a página inicial da aplicação com informações em JSON, se você acessar a &lt;code&gt;localhost:8080/pikachu&lt;/code&gt; verá informações do pokemon pikachu vindas de &lt;code&gt;https://pokeapi.co/&lt;/code&gt;. Mas não faremos interações com a máquina física nesse post. Por padrão o docker possui configurações de iptables que permitem criações de containers seguros. os comandos acima possuem algumas flags que modificam algumas regras internas do docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:80&lt;/code&gt; libera a porta 80 na porta 8080 da maquina física&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--cap-add=NET_ADMIN --cap-add=NET_RAW&lt;/code&gt; permite que usemos o container como um servidor e configuremos suas próprias regras de firewall.
Para simplificar o estudo do iptables nesse post, não iremos fazer configurações avançadas com o docker, apenas as interações simples da máquina &lt;code&gt;client&lt;/code&gt; com a &lt;code&gt;server&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bloqueio de ping
&lt;/h2&gt;

&lt;p&gt;Vamos identificar os ips das máquinas, para isso, com o bash das duas máquinas ligadas vamos digitar o comando &lt;code&gt;ifconfig&lt;/code&gt; e pegar os ips no trecho inet. De modo respectivo vamo supor que temos os seguintes ips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client: &lt;code&gt;172.17.0.3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;server: &lt;code&gt;172.17.0.2&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos testar o ping do client para o servidor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping 172.17.0.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ele irá normalmente pegar o ping de &lt;code&gt;server&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Com isso vamos adicionar nossa primeira regra em &lt;code&gt;server&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-I&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; ICMP &lt;span class="nt"&gt;-j&lt;/span&gt; DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instantaneamente o ping para. Se excluimos a mesma regra com o comando abaixo, automaticamente o ping volta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-D&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; ICMP &lt;span class="nt"&gt;-j&lt;/span&gt; DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se usamos a flag REJECT ao inves de DROP o ping sera recusado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-I&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; ICMP &lt;span class="nt"&gt;-j&lt;/span&gt; REJECT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bloqueio de TCP
&lt;/h2&gt;

&lt;p&gt;Usando a ferramenta curl podemos acessar a máquina &lt;code&gt;server&lt;/code&gt; via http com o comando GET:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"172.17.0.2:8080"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ele irá apresentar um html semelhante ao visto no &lt;code&gt;localhost:8080&lt;/code&gt;. Para bloquear o acesso para client, usaremos seguinte comando em &lt;code&gt;server&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-I&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; TCP &lt;span class="nt"&gt;-s&lt;/span&gt; 172.17.0.3 &lt;span class="nt"&gt;-j&lt;/span&gt; DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao tentarmos novamente acessar o endereço &lt;code&gt;172.17.0.2:80&lt;/code&gt; em &lt;code&gt;client&lt;/code&gt;, não temos acesso. Para remover a regra basta executar o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-D&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; TCP &lt;span class="nt"&gt;-s&lt;/span&gt; 172.17.0.3 &lt;span class="nt"&gt;-j&lt;/span&gt; DROP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bloqueando o ip do site
&lt;/h3&gt;

&lt;p&gt;Lembra que o endereço &lt;code&gt;localhost:8080/pikachu&lt;/code&gt; levava à um json com informações detalhadas do pikachu via PokeApi? vamos bloquear o acesso ao ip da PokeApi agora. Digite comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET &lt;span class="s2"&gt;"172.17.0.2:8080/pikachu"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você verá todas as informações em json do pikachu. Considerando o ip &lt;code&gt;172.64.201.27&lt;/code&gt; e &lt;code&gt;172.64.200.27&lt;/code&gt; para o site &lt;code&gt;https://pokeapi.co/&lt;/code&gt;. Agora ao tentar novamente, ele irá rejeitar a conexão, mas o &lt;code&gt;172.17.0.2:8080&lt;/code&gt; funcionará normalmente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-I&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; TCP &lt;span class="nt"&gt;-s&lt;/span&gt; 172.64.201.27 &lt;span class="nt"&gt;-j&lt;/span&gt; REJECT
iptables &lt;span class="nt"&gt;-I&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; TCP &lt;span class="nt"&gt;-s&lt;/span&gt; 172.64.200.27 &lt;span class="nt"&gt;-j&lt;/span&gt; REJECT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;para desfazer as regras basta digitar os seguintes comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-D&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; TCP &lt;span class="nt"&gt;-s&lt;/span&gt; 172.64.201.27 &lt;span class="nt"&gt;-j&lt;/span&gt; REJECT
iptables &lt;span class="nt"&gt;-D&lt;/span&gt; INPUT &lt;span class="nt"&gt;-p&lt;/span&gt; TCP &lt;span class="nt"&gt;-s&lt;/span&gt; 172.64.200.27 &lt;span class="nt"&gt;-j&lt;/span&gt; REJECT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>doker</category>
      <category>iptables</category>
      <category>linux</category>
      <category>firewall</category>
    </item>
    <item>
      <title>Realizando ataques de força bruta em containers docker usando hydra</title>
      <dc:creator>Filipe Câncio</dc:creator>
      <pubDate>Mon, 20 Nov 2023 22:40:13 +0000</pubDate>
      <link>https://forem.com/cancio/testando-o-hydra-com-o-docker-3ceg</link>
      <guid>https://forem.com/cancio/testando-o-hydra-com-o-docker-3ceg</guid>
      <description>&lt;p&gt;Neste post iremos entender como usar a ferramenta hydra para ataques de força bruta e de dicionário através de um site ou de um computador para outro. Podemos entender por definição:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Um &lt;strong&gt;ataque de dicionário&lt;/strong&gt; é um ataque às senhas que &lt;strong&gt;usa palavras ou frases comuns encontradas em dicionários para comprometer credenciais de usuários&lt;/strong&gt;. Caso seja uma pessoa que usa palavras do dicionário ou frases comuns como senha, você corre o risco de ser vítima de um ataque de dicionário. Fonte: &lt;a href="https://www.keepersecurity.com/pt_BR/threats/dictionary-attack.html#:~:text=Um%20ataque%20de%20dicion%C3%A1rio%20%C3%A9,de%20um%20ataque%20de%20dicion%C3%A1rio." rel="noopener noreferrer"&gt;Keeper Security&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Brute Force é um ataque “Hacker” usado para tentar descobrir a combinação certa de uma senha, tentando várias combinações diferentes. O ataque pode ser feito de forma manual, colocando as senhas uma por vez até que a verdadeira seja encontrada. Fonte: &lt;a href="https://brasilcloud.com.br/brute-force-o-que-e-e-como-se-prevenir/#:~:text=Como%20funciona%20e%20para%20que,que%20a%20verdadeira%20seja%20encontrada." rel="noopener noreferrer"&gt;Brasil Cloud&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para realizar os ataques utilizaremos um ambiente controlado usando containers docker. Para você que é leigo com docker digamos que os dockers podem ser usados como máquinas virtuais mas de uma forma mais simples e leve, como se criar uma máquina vitual fosse como preparar uma lasanha do zero e o docker fosse uma lasanha pronta para esquentar no microondas. Ao invés de gastarmos tempo preparando os ingredientes basta pegar uma imagem pronta (seu sabor de lasanha favorito) e a partir dela preparar o seu almoço (container docker).&lt;br&gt;
A imagem que vamos usar é a &lt;a href="https://hub.docker.com/r/cancitoo/kali-linux-ssh-hydra" rel="noopener noreferrer"&gt;cancitoo/kali-linux-ssh-hydra&lt;/a&gt; basta ir na sua maquina e digitar o comando abaixo (é preciso ter o docker instalado na sua máquina):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull cancitoo/kali-linux-ssh-hydra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A aqui já temos o necessário para relizar nosso laboratório.&lt;/p&gt;

&lt;h1&gt;
  
  
  Usando ataque de dicionário em um site
&lt;/h1&gt;

&lt;p&gt;Para esse ataque iremos criar a nossa primeira máquina, aqui no exemplo usaremos o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; pc01 &lt;span class="nt"&gt;-p&lt;/span&gt; 6050:22 &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; cancitoo/kali-linux-ssh-hydra bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse comando criamos um container chamdo &lt;code&gt;pc01&lt;/code&gt; e sua porta 22 será a 6050 da máquina real, ele também já abre nossa máquina no terminal como um bash. A partir daqui já usando no terminal a nossa máquina &lt;code&gt;pc01&lt;/code&gt;. Caso no futuro você queira acessa novamente a &lt;code&gt;pc01&lt;/code&gt; basta digitar o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#para executar um container ja aberto&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; pc01 /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto! Nossa máquina já está pronta para fazer o ataque! Nesse caso, vamos usar atacar o site &lt;code&gt;http://testphp.vulnweb.com/login.php&lt;/code&gt; com o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hydra testphp.vulnweb.com http-form-post &lt;span class="s2"&gt;"/userinfo.php:uname=^USER^&amp;amp;pass=^PASS^:login page"&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 0000 &lt;span class="nt"&gt;-t&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui podemos observar que o hydra faz o ataque via uma requisição http inserindo os valores de user com  a flag &lt;code&gt;-l&lt;/code&gt; e senha &lt;code&gt;-P&lt;/code&gt; de forma respectiva nos parametros &lt;code&gt;USER&lt;/code&gt; e &lt;code&gt;PASS&lt;/code&gt; dentro endereço usado. O ataque deu errado pois a senha do comando acima &lt;code&gt;0000&lt;/code&gt; não é a correta. Agora vamos montar em &lt;code&gt;pc01&lt;/code&gt; nosso próprio dicionário. Digite o comando abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano /tmp/pass.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;vai aparece o editor nano, coloque nele uma lista de possíveis senhas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000
1234
4321
3434
4545
teste
nome
nada
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos rodar novamente o comando mas desta vez com a flag de password em maiusculo usando nosso novo arquivo &lt;code&gt;/tmp/pass.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hydra testphp.vulnweb.com http-form-post &lt;span class="s2"&gt;"/userinfo.php:uname=^USER^&amp;amp;pass=^PASS^:login page"&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; /tmp/pass.txt &lt;span class="nt"&gt;-t&lt;/span&gt; 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desta vez o docker irá rodar todo o arquivo &lt;code&gt;/tmp/pass.txt&lt;/code&gt; procurando a senha correta. Assim ocorre o ataque de força brutaa. Dest vez vai dar certo o ataque pois a senha correta &lt;code&gt;teste&lt;/code&gt; consta no nosso dicionário.&lt;/p&gt;

&lt;h1&gt;
  
  
  atacando uma maquina para a outra via ssh
&lt;/h1&gt;

&lt;p&gt;Agora vamos criar uma nova máquina &lt;code&gt;pc02&lt;/code&gt; semelhante ao que fizemos com &lt;code&gt;p01&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; pc02 &lt;span class="nt"&gt;-p&lt;/span&gt; 6051:22 &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; cancitoo/kali-linux-ssh-hydra bash

&lt;span class="c"&gt;#para executar um container ja aberto&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; pc02 /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repare que dessa vez a porta 22 é a 6051 da maquina real. Vamos adicionar uma camada de segurança em &lt;code&gt;pc02&lt;/code&gt;. Por padrão o container não vem com senha, para configurar a senha de &lt;code&gt;pc02&lt;/code&gt; basta digitar o comando abaixo e seguir as instruções:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#para gerar uma senha pro root&lt;/span&gt;
passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos configurar o ssh na máquina &lt;code&gt;pc02&lt;/code&gt;. Isso vai permitir  conexão ssh de &lt;code&gt;pc01&lt;/code&gt; para &lt;code&gt;pc02&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#definir da chave de acesso remota&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-A&lt;/span&gt;

&lt;span class="c"&gt;#iniciar o serviço SSH&lt;/span&gt;
service ssh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voltando para &lt;code&gt;pc01&lt;/code&gt; vamos adicionar  senha criada em &lt;code&gt;pc02&lt;/code&gt; no nosso dicionário e criar um novo dicionário com logins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Atualizar dicionario com senha&lt;/span&gt;
nano /tmp/pass.txt
&lt;span class="c"&gt;# criar lista de possíveis usuários&lt;/span&gt;
nano /tmp/users.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui vai um exemplo para &lt;code&gt;/tmp/users.txt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pedro
carlo
root
admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas ainda falta saber qual o ip de &lt;code&gt;pc02&lt;/code&gt;, para isso vamos rodar esse comando em um terminal à parte:&lt;br&gt;
abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"{{ .NetworkSettings.IPAddress }}"&lt;/span&gt; pc02
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos fazer de conta que a respota veio &lt;code&gt;172.17.0.2&lt;/code&gt;. Agora basta executar hydra na porta de ataque&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; hydra &lt;span class="nt"&gt;-L&lt;/span&gt; /tmp/users.txt &lt;span class="nt"&gt;-P&lt;/span&gt; /tmp/pass.txt 172.17.0.2 ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>hydra</category>
      <category>docker</category>
      <category>kali</category>
      <category>linux</category>
    </item>
    <item>
      <title>Renovação de Matrícula 2022.2</title>
      <dc:creator>Filipe Câncio</dc:creator>
      <pubDate>Thu, 04 Aug 2022 03:23:28 +0000</pubDate>
      <link>https://forem.com/dasi/renovacao-de-matricula-20222-2b4n</link>
      <guid>https://forem.com/dasi/renovacao-de-matricula-20222-2b4n</guid>
      <description>&lt;p&gt;Já está disponível a renovação de matrícula para o semestre de 2022.2 para os cursos subsequentes e superiores do IFBA de Vitória da Conquista-BA. Ela estará diponível entre os dias 04 e 07 de agosto de 2022 e para realização basta acessar a plataforma do &lt;a href="https://suap.ifba.edu.br/" rel="noopener noreferrer"&gt;SUAP&lt;/a&gt; clicar em "faça sua matrícula online". O sistema solicitará uma atualização dos dados cadastrais antes da matrícula.&lt;br&gt;
Caso queira consultar a lista de matérias disponíveis para este semestre, basta a acessar a &lt;a href="https://docs.google.com/spreadsheets/d/1CSP2PIXjvxz45IFtlpKIbj4RK0xkyS4ZUdChLXO20jc/edit#gid=2115886481" rel="noopener noreferrer"&gt;Lista de Horários 2022.2&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ifba</category>
      <category>matricula</category>
      <category>renovacao</category>
    </item>
    <item>
      <title>O Guia do Estudante do IFBA</title>
      <dc:creator>Filipe Câncio</dc:creator>
      <pubDate>Thu, 04 Aug 2022 03:09:19 +0000</pubDate>
      <link>https://forem.com/dasi/o-guia-do-estudante-do-ifba-6m5</link>
      <guid>https://forem.com/dasi/o-guia-do-estudante-do-ifba-6m5</guid>
      <description>&lt;p&gt;Este post é um teste&lt;/p&gt;

</description>
      <category>ifba</category>
      <category>bsi</category>
      <category>sistemas</category>
    </item>
  </channel>
</rss>
