<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Musings from Etienne — RSS Feed]]></title><description><![CDATA[My blog covering mostly technical subjects around web application security, serverless architectures, distributed systems and other cloud computing topics.]]></description><link>https://etiennemunnich.github.io</link><generator>GatsbyJS</generator><lastBuildDate>Thu, 02 Apr 2026 11:25:45 GMT</lastBuildDate><item><title><![CDATA[re:invent 2025 - State of the Edge: Delivery of the web with CloudFront, WAF, & Shield (NET211)]]></title><description><![CDATA[Another re:invent in the books — great to be back in Las Vegas presenting on something I care deeply about. AWS re:Invent 2025 — State of…]]></description><link>https://etiennemunnich.github.io/reinvent-2025-state-of-the-edge/</link><guid isPermaLink="false">https://etiennemunnich.github.io/reinvent-2025-state-of-the-edge/</guid><pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Another re:invent in the books — great to be back in Las Vegas presenting on something I care deeply about.&lt;/p&gt;
&lt;h2&gt;AWS re:Invent 2025 — State of the Edge: Delivery of the web with CloudFront, WAF, &amp;#x26; Shield (NET211)&lt;/h2&gt;
&lt;p&gt;As the internet evolves with new clients, protocols, and threats, leveraging global edge infrastructure has become critical for delivering exceptional user experiences. In this session, we examined the broader trajectory of the web — from the proliferation of mobile-first experiences to the rise of AI workloads and emerging security threats.&lt;/p&gt;
&lt;p&gt;We explored how Amazon CloudFront, AWS Global Accelerator, AWS WAF, and AWS Shield have integrated to address today&apos;s most pressing web performance and security challenges, and how AWS is positioning its infrastructure to meet tomorrow&apos;s.&lt;/p&gt;
&lt;p&gt;Ambrose Phey from Atlassian also joined to share how they&apos;ve incorporated AWS edge networking services as foundational components to deliver fast and secure web applications at scale.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/j8uPcCJQGYo?si=Uat48yhA8-OqMkJM&quot; title=&quot;AWS re:Invent 2025 - State of the Edge: Delivery of the web with CloudFront, WAF, &amp;amp; Shield (NET211)&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;
&lt;h2&gt;Presented with&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nishit Sawhney&lt;/strong&gt; — Director, Amazon CloudFront, AWS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ambrose Phey&lt;/strong&gt; — Atlassian&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Building with Coding AI Tools]]></title><description><![CDATA[Because Why Not Let Robots Write Your Blog? A technical deep-dive into integrating Perplexity AI’s language models, or, “How I taught my…]]></description><link>https://etiennemunnich.github.io/building-with-coding-ai-tools/</link><guid isPermaLink="false">https://etiennemunnich.github.io/building-with-coding-ai-tools/</guid><pubDate>Sun, 23 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Because Why Not Let Robots Write Your Blog?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A technical deep-dive into integrating Perplexity AI’s language models, or, “How I taught my computer to argue with itself.”&lt;/p&gt;
&lt;p&gt;So, you want to make your Python app talk to Perplexity AI? Great! Because nothing says “cutting-edge” like outsourcing your brainpower to a server farm. In this article, I’ll dive into an example built with Amazon Q Developer, Perplexity and a few other tools. Maybe, just maybe, figure out if this is a good idea.&lt;/p&gt;
&lt;p&gt;My effort; it’s a brautiful mess but works: &lt;a href=&quot;https://github.com/etiennemunnich/modsec-crs-rule-explainer&quot;&gt;Modsecurity Rule Explainer&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Project Overview&lt;/h2&gt;
&lt;p&gt;I started by trying to create a “flexible” language model interface. Translation: making it so you can swap out AI providers like you swap out socks or trying a new flavour of ice cream. There’s always a new flavour, or something like that. Except, instead of smelly feet, you get… well, potentially tastey AI responses.&lt;/p&gt;
&lt;h2&gt;Key Components&lt;/h2&gt;
&lt;h3&gt;Penmenship lands better outcomes&lt;/h3&gt;
&lt;p&gt;Start with a plan, think of it as building psudeo code and request workflows ahead of time. This helps you understand the requirements. But the trick not only building great prompts, but knowing that these tools get it wrong (a lot).&lt;/p&gt;
&lt;p&gt;Prompts MUST declare specific goals, steps, formats, constraints, etc. It’s a double edged sword to ask for best practises and error handling or test driven approaches as this often lands the models jumping down the prverbial rabbit hole and not delivering on the actual outcome you want.&lt;/p&gt;
&lt;h3&gt;Base LLM Interface&lt;/h3&gt;
&lt;p&gt;In the code example I built, I started using fancy “abstract base classes” to make sure all the AI buddies behave. Think of it as putting them in a digital kindergarten:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;from abc import ABC, abstractmethod
from typing import Dict, Any

class LLMProvider(ABC):
    &quot;&quot;&quot;Base class for all LLM providers. Basically, the boss telling them what to do.&quot;&quot;&quot;
    
    def __init__(self, api_key: str):
        self.api_key = api_key # The magic password to make them work.
    
    @abstractmethod
    def analyze(self, prompt: str) -&gt; Dict[str, Any]:
        &quot;&quot;&quot;Analyze text using the LLM provider. Or, &quot;Think, robot, THINK!&quot; &quot;&quot;&quot;
        pass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Perplexity Integration&lt;/h3&gt;
&lt;p&gt;Hooking up to Perplexity AI with all the grace of a toddler trying to plug in a USB:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;from typing import Dict, Any
from .base import LLMProvider
import httpx

class PerplexityProvider(LLMProvider):
    &quot;&quot;&quot;Implementation of LLMProvider for Perplexity AI. Or, &quot;The robot that actually answers.&quot; &quot;&quot;&quot;
    
    def __init__(self, api_key: str):
        super().__init__(api_key) # Super means &quot;Do what your robot parents told you.&quot;
        self.client = httpx.Client(
            base_url=&quot;[https://api.perplexity.ai](https://api.perplexity.ai)&quot;, # Where the robot lives.
            headers={&quot;Authorization&quot;: f&quot;Bearer {api_key}&quot;} # The robot&apos;s password.
        )
    
    def analyze(self, prompt: str) -&gt; Dict[str, Any]:
        &quot;&quot;&quot;Analyze text using Perplexity AI&apos;s API. Or, &quot;Robot, tell me something interesting.&quot; &quot;&quot;&quot;
        response = self.client.post(&quot;/chat/completions&quot;, json={
            &quot;model&quot;: &quot;pplx-7b-chat&quot;, # The robot&apos;s brain.
            &quot;messages&quot;: [{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: prompt}] # What we&apos;re asking the robot.
        })
        return response.json() # The robot&apos;s answer.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Factory Pattern Implementation&lt;/h3&gt;
&lt;p&gt;Figuring out a “factory pattern”, to create robot instances. Because who wants to manually assemble robots?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;class LLMFactory:
    &quot;&quot;&quot;Factory class for creating LLM providers. Or, the robot assembly line.&quot;&quot;&quot;
    _providers: Dict[str, Type[LLMProvider]] = {} # Where we keep the robot parts.

    @classmethod
    def create(cls, provider_name: str, api_key: str) -&gt; LLMProvider:
        &quot;&quot;&quot;Create an instance of the specified LLM provider. Or, &quot;Build me a robot!&quot; &quot;&quot;&quot;
        if provider_name not in cls._providers:
            raise ValueError(f&quot;Unknown provider: {provider_name}&quot;) # &quot;Sorry, we don&apos;t have that model in stock.&quot;
        return cls._providers[provider_name](api_key) # Here&apos;s your robot!

    @classmethod
    def register_provider(cls, name: str, provider_class: Type[LLMProvider]):
        &quot;&quot;&quot;Register a new provider class. Or, &quot;Add a new robot to the assembly line.&quot; &quot;&quot;&quot;
        cls._providers[name] = provider_class # Put the robot parts in the machine.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Technical Implementation&lt;/h3&gt;
&lt;p&gt;Security considerations, built in patterns out the box. Whilst these code companions are constantly evolving, nearly all the tools I tested had a measure of common sense approaches to building secure code. For example, using environment variables, because hardcoding API keys is like leaving your front door unlocked with a sign that says “Please rob me.”
Usage Examples&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;def get_llm_client(api_key: str, provider: str = &quot;perplexity&quot;):
    &quot;&quot;&quot;Initialize and return an LLM client instance. Or, &quot;Get me a robot to talk to.&quot; &quot;&quot;&quot;
    return LLMFactory.create(
        provider_name=provider,
        api_key=api_key # The robot&apos;s secret password.
    )

# Create an instance and analyze text. Or, &quot;Ask the robot something profound.&quot;
llm = get_llm_client(api_key=&quot;your-api-key&quot;)
response = llm.analyze(&quot;Explain the meaning of life, and also, what&apos;s for dinner?&quot;) 
   # Multitasking robots.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Testing and Quality Assurance&lt;/h3&gt;
&lt;p&gt;I really like testing everything TDD, because I wouldn’t trust a robot that hasn’t been thoroughly interrogated, would you? In one example, I built the desired example output JSON events and ask the code to build accordingly, code quality was pretty spot on.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We’ve successfully built a system to talk to Perplexity AI. Now, if it leads to a robot uprising or just better blog posts, only time will tell.&lt;/p&gt;
&lt;p&gt;Note: For detailed setup instructions and API documentation, please refer to the project’s README.md file. Or, ask a robot. They probably know.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[re:invent 2024 - protecting against DDoS events]]></title><description><![CDATA[I had a wonderful time meeting customers and presenting at re:invent ‘24! AWS re:Invent 2024 - You are under a DDOS attack! Are you ready to…]]></description><link>https://etiennemunnich.github.io/reinvent-2024-protecting-against-ddos-events/</link><guid isPermaLink="false">https://etiennemunnich.github.io/reinvent-2024-protecting-against-ddos-events/</guid><pubDate>Fri, 06 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I had a wonderful time meeting customers and presenting at re:invent ‘24!&lt;/p&gt;
&lt;h2&gt;AWS re:Invent 2024 - You are under a DDOS attack! Are you ready to respond? (CDN306)&lt;/h2&gt;
&lt;p&gt;Do your operational teams know how to respond in the event of an attack? Have you architected with a DDOS strategy in mind? This talk guides you through the steps that help you react when under attack. Explore AWS tools you should leverage and best practices you can follow to proactively prepare for such scenarios. Learn how to identify and respond to DDOS attacks using services such as Amazon CloudFront, AWS WAF, and AWS Shield Advanced.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/oXw0vLOSIY4&quot; title=&quot;AWS re:Invent 2024 - You are under a DDoS attack! Are you ready to respond? (CDN306)&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;</content:encoded></item><item><title><![CDATA[re:inforce 2024 presentation with catch]]></title><description><![CDATA[I had the amazing priviledge to co-present at re:inforce! AWS re:Inforce 2024 - How Catch Group uses AWS WAF Bot Control on their ecommerce…]]></description><link>https://etiennemunnich.github.io/reinforce-2024-presentation-with-catch/</link><guid isPermaLink="false">https://etiennemunnich.github.io/reinforce-2024-presentation-with-catch/</guid><pubDate>Thu, 13 Jun 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I had the amazing priviledge to co-present at re:inforce!&lt;/p&gt;
&lt;h2&gt;AWS re:Inforce 2024 - How Catch Group uses AWS WAF Bot Control on their ecommerce platform (NIS306)&lt;/h2&gt;
&lt;p&gt;In the fast-paced world of ecommerce, security is crucial. This session explores Catch Group’s journey, the lessons they learned, and how AWS security services empowered them to improve safeguards for their ecommerce platform and customer experience. By leveraging AWS WAF Bot Control for targeted bots, AWS WAF Fraud Control for account takeover prevention, and AWS Shield Advanced, Catch Group was able to gain better visibility into potential threats. This allowed them to identify and implement targeted mitigations to protect against bots, DDoS attacks, and account takeover fraud. As a result, Catch Group was able to provide their customers with a secure and reliable shopping experience.&lt;/p&gt;
&lt;div class=&quot;gatsby-resp-iframe-wrapper&quot; style=&quot;padding-bottom: 56.25%; position: relative; height: 0; overflow: hidden; margin-bottom: 1.0725rem&quot; &gt; &lt;iframe src=&quot;https://www.youtube.com/embed/oAAg73BNdxQ&quot; title=&quot;AWS re:Inforce 2024 - How Catch Group uses AWS WAF Bot Control (NIS306)&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; style=&quot; position: absolute; top: 0; left: 0; width: 100%; height: 100%; &quot;&gt;&lt;/iframe&gt; &lt;/div&gt;</content:encoded></item><item><title><![CDATA[re:invent 2023 - Designing a secure perimeter with cost in mind]]></title><description><![CDATA[So grateful to have had the chance to co-present a chalk talk at re:invent! re:invent 2023 - Designing a secure perimeter with cost in mind…]]></description><link>https://etiennemunnich.github.io/reinvent-designing-a-secure-perimeter/</link><guid isPermaLink="false">https://etiennemunnich.github.io/reinvent-designing-a-secure-perimeter/</guid><pubDate>Thu, 07 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;So grateful to have had the chance to co-present a chalk talk at re:invent!&lt;/p&gt;
&lt;h2&gt;re:invent 2023 - Designing a secure perimeter with cost in mind&lt;/h2&gt;
&lt;p&gt;Co-presentated with Damindra Bandara.&lt;/p&gt;
&lt;p&gt;In this chalk talk, you will learn how to optimize your monthly AWS spend leveraging Amazon Security Services (Amazon CloudFront, AWS Shield, AWS WAF and AWS Global Accelerator) to design a secure perimeter. This session will outline in detail optimization techniques including: optimizing data egress costs using Savings Bundles, DDoS cost prevention, cost optimized configurations, WAF cost optimization, and visibility options such as usage trends and cost explorer. Attendees will get an opportunity to ask questions regarding their use cases and understand how to save their perimeter security cost.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Detect and block advanced bot traffic with AWS WAF]]></title><description><![CDATA[I published a post on the AWS Security Blog covering the newly launched AWS WAF Bot Control for Targeted Bots. Targeted bots are the hard…]]></description><link>https://etiennemunnich.github.io/detect-and-block-advanced-bot-traffic/</link><guid isPermaLink="false">https://etiennemunnich.github.io/detect-and-block-advanced-bot-traffic/</guid><pubDate>Fri, 11 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I published a post on the AWS Security Blog covering the newly launched &lt;strong&gt;AWS WAF Bot Control for Targeted Bots&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Targeted bots are the hard problem — they mimic human behaviour, rotate IPs, and bypass simple rate limits. The new targeted inspection level uses browser fingerprinting and client-side JavaScript interrogation to catch them, without requiring any changes to your application or architecture.&lt;/p&gt;
&lt;p&gt;The post walks through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The difference between &lt;strong&gt;common&lt;/strong&gt; and &lt;strong&gt;targeted&lt;/strong&gt; bot inspection levels&lt;/li&gt;
&lt;li&gt;Configuring per-category actions — block, challenge, CAPTCHA, count, allow&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scope-down statements&lt;/strong&gt; to limit Bot Control to the URIs that actually need it (login, checkout) and keep costs sane&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Token domains&lt;/strong&gt; — a single web ACL accepting WAF tokens across multiple domains and CloudFront distributions&lt;/li&gt;
&lt;li&gt;Embedding the &lt;strong&gt;JavaScript Application Integration SDK&lt;/strong&gt; so WAF can reject tokenless requests outright&lt;/li&gt;
&lt;li&gt;Rule ordering and CloudWatch alarm setup for token-absent spikes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;→ &lt;a href=&quot;https://aws.amazon.com/blogs/security/detect-and-block-advanced-bot-traffic/&quot;&gt;Read the full post on the AWS Security Blog&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[update to the blog]]></title><description><![CDATA[Welcome to my blog! As a Senior Edge Specialist Solutions Architect at AWS, I’ll be sharing insights and experiences from the forefront of…]]></description><link>https://etiennemunnich.github.io/welcome/</link><guid isPermaLink="false">https://etiennemunnich.github.io/welcome/</guid><pubDate>Sat, 01 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to my blog! As a Senior Edge Specialist Solutions Architect at AWS, I’ll be sharing insights and experiences from the forefront of cloud computing, with a particular focus on Edge services and distributed systems. My goal is to contribute practical knowledge to the technical community, especially in areas where performance, security, and global scale intersect.&lt;/p&gt;
&lt;h2&gt;What to Expect&lt;/h2&gt;
&lt;p&gt;I plan to write about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Edge Computing &amp;#x26; Content Delivery&lt;/strong&gt;: Optimizing global content delivery through AWS Edge services including CloudFront, Lambda@Edge, and CloudFront Functions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security Architecture&lt;/strong&gt;: Building secure, resilient applications using AWS Shield Advanced, WAF, and security best practices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Serverless Architecture&lt;/strong&gt;: Designing scalable, efficient serverless solutions with Lambda, API Gateway, and other Edge computing services.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure as Code&lt;/strong&gt;: Automating infrastructure deployment using AWS CDK and CloudFormation with multi-region considerations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Solution Architecture&lt;/strong&gt;: Implementing enterprise-scale architectural patterns focused on performance, security, and cost optimization.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Technical Focus&lt;/h2&gt;
&lt;p&gt;My posts will include practical examples in Python, Go, and Node.js, along with infrastructure-as-code samples using AWS CDK and CloudFormation. I’ll share real-world scenarios, architectural decisions, and lessons learned from helping organizations across Australia and New Zealand, as well as multinational enterprises.&lt;/p&gt;
&lt;h2&gt;Stay Connected&lt;/h2&gt;
&lt;p&gt;Subscribe to the RSS feed or follow me on social media to stay updated with new posts. I welcome discussions and knowledge sharing from the community.&lt;/p&gt;
&lt;p&gt;Looking forward to sharing insights and learning together!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[opencanary honey pot - part of my zero day initiative]]></title><description><![CDATA[It’s been a while :] But back to the grind stone, my nextr 1 day project was based out of curiousity about what was happening on my DSL…]]></description><link>https://etiennemunnich.github.io/opencanary-honey-pot/</link><guid isPermaLink="false">https://etiennemunnich.github.io/opencanary-honey-pot/</guid><pubDate>Mon, 23 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It’s been a while :] But back to the grind stone, my nextr 1 day project was based out of curiousity about what was happening on my DSL router as as an attack surface after reading about common attacks to type home routers.&lt;/p&gt;
&lt;p&gt;Fair warning - don’t open your router up to the net without understanding the risks - you’re letting the world into your home. I used a spare router…&lt;/p&gt;
&lt;h2&gt;The plan&lt;/h2&gt;
&lt;p&gt;So the plan was to grab inbound UDP and TCP connection data to ports 80(HTTP), 22(SSH) and 21(FTP). Unfortunately I couldn’t capture ICMP due to the router used (locked config by upstream provider)&lt;/p&gt;
&lt;p&gt;Further ideas would be to capture any scans within my network for SMB(Samba / File Shares) and all DNS queries as a trip wire as to check if someone is in the network.&lt;/p&gt;
&lt;p&gt;This is where OpenCanary was of interest for me, I wanted to gather data to see what type of attacks where occurring, from where and gather a user/password list of all the attack/discovery attempts. OpenCanary allows open to get going pretty quickly, it simulates services so that attackers attempt to connect which is then logged in detail….&lt;/p&gt;
&lt;h2&gt;Why use a honeypot?&lt;/h2&gt;
&lt;p&gt;The attempts to connect to ‘fake’ services allows SecOps (seucity operations) staff to understand what attackers are trying to do and potentially block IP address, put checks in place in production systems, prevent username and/or password combinations from being used on networks and the internet.&lt;/p&gt;
&lt;p&gt;OpenCanary can easily be used within a LAN or on the internet, attackers could already be in your network :[…&lt;/p&gt;
&lt;h2&gt;Equipment used for my test&lt;/h2&gt;
&lt;p&gt;I used stock kit provided by my ISP, with only the and decided to dust of my Raspberry Pi (rpi) with the out the box rasbian OS. This was the only item connected as I don’t want the world having the opertunity to have access to my home network.&lt;/p&gt;
&lt;p&gt;Oversimplified install steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configure router to port forward, disable any DDOS, port triggering&lt;/li&gt;
&lt;li&gt;Rasberry Pi - install rasbian, configure sshd to use port 222 and configure ufw, limit port 222 to listen to a particular IP from which admin actions will be done, allow port 80, 21, 22 access from any ip (for the honey pot to capture)&lt;/li&gt;
&lt;li&gt;Install OpenCanary and configure the services in /etc/opencanaryd/opencanary.conf&lt;/li&gt;
&lt;li&gt;Configure opencanaryd to start at boot using your prefer method…&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Logs&lt;/h2&gt;
&lt;p&gt;I started receiving attempts against all ports immediately, the logs for&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;web services land in /var/tmp/opencanary.log&lt;/li&gt;
&lt;li&gt;samba/SMB land in /var/log/samba-audit.log…&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;{&quot;dst_host&quot;: &quot;10.0.0.2&quot;, &quot;dst_port&quot;: &quot;22&quot;, &quot;local_time&quot;: &quot;2019-09-01 13:13:36.569491&quot;, &quot;logdata&quot;: {&quot;DF&quot;: &quot;&quot;, &quot;ID&quot;:&quot;34943&quot;, &quot;IN&quot;: &quot;xxxx&quot;, &quot;LEN&quot;: &quot;60&quot;, &quot;MAC&quot;: &quot;zz:zz:z3:3z:zz:11:11:11:00:22:44:17:28:00&quot;, &quot;OUT&quot;: &quot;&quot;, &quot;PREC&quot;: &quot;0x00&quot;, &quot;PROTO&quot;: &quot;TCP&quot;, &quot;RES&quot;: &quot;0x00&quot;, &quot;SYN&quot;: &quot;&quot;, &quot;TOS&quot;: &quot;0x00&quot;, &quot;TTL&quot;: &quot;42&quot;, &quot;URGP&quot;: &quot;0&quot;, &quot;WINDOW&quot;: &quot;14440&quot;}, &quot;logtype&quot;: 5001, &quot;node_id&quot;: &quot;my-rpi-canary&quot;, &quot;src_host&quot;: &quot;11.11.112.71&quot;, &quot;src_port&quot;: &quot;60831&quot;}
{&quot;dst_host&quot;: &quot;10.0.0.2&quot;, &quot;dst_port&quot;: 22, &quot;local_time&quot;: &quot;2019-09-01 13:13:37.530184&quot;, &quot;logdata&quot;: {&quot;SESSION&quot;: &quot;603&quot;}, &quot;logtype&quot;: 4000, &quot;node_id&quot;: &quot;my-rpi-canary&quot;, &quot;src_host&quot;: &quot;11.11.112.71&quot;, &quot;src_port&quot;: 60831}
{&quot;dst_host&quot;: &quot;10.0.0.2&quot;, &quot;dst_port&quot;: 22, &quot;local_time&quot;: &quot;2019-09-01 13:13:41.151453&quot;, &quot;logdata&quot;: {&quot;LOCALVERSION&quot;: &quot;SSH-2.0-OpenSSH_5.1p1 Debian-4&quot;, &quot;REMOTEVERSION&quot;: &quot;SSH-2.0-PUTTY&quot;}, &quot;logtype&quot;: 4001, &quot;node_id&quot;: &quot;my-rpi-canary&quot;, &quot;src_host&quot;: &quot;11.11.112.71&quot;, &quot;src_port&quot;: 60831}
{&quot;dst_host&quot;: &quot;10.0.0.2&quot;, &quot;dst_port&quot;: 22, &quot;local_time&quot;: &quot;2019-09-01 13:13:43.225079&quot;, &quot;logdata&quot;: {&quot;LOCALVERSION&quot;: &quot;SSH-2.0-OpenSSH_5.1p1 Debian-4&quot;, &quot;PASSWORD&quot;: &quot;daniel&quot;, &quot;REMOTEVERSION&quot;: &quot;SSH-2.0-PUTTY&quot;, &quot;USERNAME&quot;: &quot;root&quot;}, &quot;logtype&quot;:4002, &quot;node_id&quot;: &quot;my-rpi-canary&quot;, &quot;src_host&quot;: &quot;11.11.112.71&quot;, &quot;src_port&quot;: 60831} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is an ability to push alerts to Slack and push logs using the OpenCanary Correlator, more on this soon.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[some news and podcasts]]></title><description><![CDATA[Whilst I haven’t posted I’ve been studying towards certifications, here are some worthy news items links & podcasts I’m listening to at the…]]></description><link>https://etiennemunnich.github.io/some-news-and-podcasts/</link><guid isPermaLink="false">https://etiennemunnich.github.io/some-news-and-podcasts/</guid><pubDate>Mon, 01 Jul 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Whilst I haven’t posted I’ve been studying towards certifications, here are some worthy news items&lt;/p&gt;
&lt;h2&gt;links &amp;#x26; podcasts I’m listening to at the moment&lt;/h2&gt;
&lt;p&gt;HAProxy agent for ModSecurity web application firewall - jcmoraisjr/modsecurity-spoa - &lt;a href=&quot;https://github.com/jcmoraisjr/modsecurity-spoa&quot;&gt;https://github.com/jcmoraisjr/modsecurity-spoa&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Like any other field, the world of Software Development has some interesting and famous rules, principles and laws - &lt;a href=&quot;https://www.timsommer.be/famous-laws-of-software-development/&quot;&gt;https://www.timsommer.be/famous-laws-of-software-development/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Podcasts: DarkNet Diaries, Data Engineering Podcast, JS Party&lt;/p&gt;</content:encoded></item><item><title><![CDATA[load testing with h2load]]></title><description><![CDATA[some basic load testing wirth h2load - there are far better tools for load testing, but sometimes one needs a quick n dirty load testing…]]></description><link>https://etiennemunnich.github.io/load-testing-with-h2load/</link><guid isPermaLink="false">https://etiennemunnich.github.io/load-testing-with-h2load/</guid><pubDate>Wed, 08 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;some basic load testing wirth h2load - there are far better tools for load testing, but sometimes one needs a quick n dirty load testing tool which h2load can help with.&lt;/p&gt;
&lt;h2&gt;Why did I use h2load?&lt;/h2&gt;
&lt;p&gt;h2load is a HTTP2 and HTTP1.1 tool from the nghttp2 package, the implementation of HTTP2 is pretty solid and verbose logging is pretty detailed. Also very easy to get going, for instance here is a basic command to hit an endpoint with 100 requests:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; h2load -n100 http://someendpoint
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To really start pushing some numbers start to play with the number of threads and clients:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; h2load --warm-up-time 5 https://yourtestwebsite -c10 -t2 -n100
starting benchmark...
spawning thread #0: 5 total client(s). 50 total requests
spawning thread #1: 5 total client(s). 50 total requests
TLS Protocol: TLSv1.2
Cipher: ECDHE-RSA-AES128-GCM-SHA256
Server Temp Key: ECDH P-256 256 bits
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done

finished in 26.75s, 3.74 req/s, 1.79MB/s
requests: 100 total, 100 started, 100 done, 100 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 100 2xx, 0 3xx, 0 4xx, 0 5xx

traffic: 47.78MB (50102431) total, 107.52KB (110100) headers (space savings 0.00%), 47.64MB (49951217) data
                     min         max         mean         sd        +/- sd
time for request:   690.85ms       5.95s       2.06s       1.43s    79.00%
time for connect:    24.21ms     27.18ms     25.01ms      1.11ms    80.00%
time to 1st byte:   261.91ms    875.21ms    415.44ms    247.46ms    80.00%
req/s           :       0.37        0.78        0.51        0.13    60.00%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Monitor for 5xx errors and time for requests, connection and to 1st byte, high values could indicate an issue that needs to be dealt with (ie add some caching in, etc etc)&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nghttp2.org/documentation/h2load.1.html&quot;&gt;nghttp2 h2load documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[interesting links and github repos]]></title><description><![CDATA[Interesting Links & Github Repos I’ve created a discord channel to be a more realtime way to reach out and chat about projects and some of…]]></description><link>https://etiennemunnich.github.io/interesting-links-and-github-repos/</link><guid isPermaLink="false">https://etiennemunnich.github.io/interesting-links-and-github-repos/</guid><pubDate>Wed, 01 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links &amp;#x26; Github Repos&lt;/h2&gt;
&lt;p&gt;I’ve created a &lt;a href=&quot;https://discord.com/channels/907076068098334800/907076068098334803&quot;&gt;discord channel&lt;/a&gt; to be a more realtime way to reach out and chat about projects and some of the cool stuff you may be working through.&lt;/p&gt;
&lt;p&gt;A cool collection of &lt;a href=&quot;https://github.com/stelligent/cloudformation_templates&quot;&gt;CloudFormation Templates&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Decode JWT tokens (useful for debugging SSO signon issues): &lt;a href=&quot;https://jwt.io/&quot;&gt;https://jwt.io/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;BBR - Congestion Control Research - TCP delay-controlled TCP flow control algorithm from Google - &lt;a href=&quot;https://blog.apnic.net/2017/05/09/bbr-new-kid-tcp-block/&quot;&gt;https://blog.apnic.net/2017/05/09/bbr-new-kid-tcp-block/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sysctl Performance Research - &lt;a href=&quot;https://wiki.mikejung.biz/Sysctl_tweaks&quot;&gt;https://wiki.mikejung.biz/Sysctl_tweaks&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[dns over https]]></title><description><![CDATA[This had been an interesting dive into the next generation of securing DNS interactions. I’ll deal with DOT (DNS over TLS) in a seperate…]]></description><link>https://etiennemunnich.github.io/dns-over-https/</link><guid isPermaLink="false">https://etiennemunnich.github.io/dns-over-https/</guid><pubDate>Mon, 22 Apr 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This had been an interesting dive into the next generation of securing DNS interactions. I’ll deal with DOT (DNS over TLS) in a seperate post to focus on DOH (DNS over HTTPS) in this post.&lt;/p&gt;
&lt;h2&gt;DNS over HTTPS:&lt;/h2&gt;
&lt;p&gt;Why would has the IETF decided to use this approach? From the RFC. Well frankly DNSSEC failed to get wide spread adoption, and since DNS was designed in the days where security the use and protocol was not really a consideration there has to be a new approach to help prevent bad actors poisoning and interfering with DNS operation. DOH albeit controvercially has been given the green light by the IETF. So per the RFC, why DOH:&lt;/p&gt;
&lt;p&gt;These use cases are preventing on-path devices from interfering with DNS operations(1), and also allowing web applications to access DNS information via existing browser APIs (2) in a safe way
consistent with Cross Origin Resource Sharing (CORS)&lt;/p&gt;
&lt;p&gt;Okay, so the plan is (1) to prevent DNS operations from being messed with by upstream DNS services, as the resolvers communications will be encrypted between the client and the DNS server/resolver (HTTPS). This has some interesting implications:&lt;/p&gt;
&lt;p&gt;The client can choose to ignore an invalid certificate presented by DOH DNS resolver, but in general terms this is an issue with any HTTPS/TLS situation for any web service.&lt;/p&gt;
&lt;p&gt;Pretty much means anyone can stand up a server with a valid cert and start serving DOH, as long as the CA from the cert is on the Mozilla list.&lt;/p&gt;
&lt;p&gt;Controlling client DNS queries from within a corporate network to outside resolvers is often something network/firewall admins do to help protectect there networks. This may prove be more difficult with DOH, as browsers/applications could be setup to drectly make DNS queries to resolvers outside the network and bypass proxies/UTM DNS checking. In saying this UTM’s could potentially prevent queries using certain content or header evaluations to detect that are particular to DOH and prevent them, not as simple as blocking UDP/TCP on port 53.&lt;/p&gt;
&lt;p&gt;One will need a DNS proxy to allow for applications that do not natively support DOH for the time being. More modern application in the future may have the application logic and libraries integrated to support DOH much like Chrome and Firefox have.&lt;/p&gt;
&lt;h2&gt;CORS&lt;/h2&gt;
&lt;p&gt;CORS (2) support by resolvers ensures requests can be made across domains thereby allowing for browsers/applications supporting CORS responses to use DOH without further client security hoops to jump through.
So, how does this work in actuallity?&lt;/p&gt;
&lt;p&gt;There are only a handful resolvers supporting DOH at the moment, I’ve run some tests against Cloudflare and Google using curl (I used an older version that doesn’t support DOH natively).&lt;/p&gt;
&lt;p&gt;Using the HTTPS endpoints provided by google using curl (GET) demostrates the request and responses structure [a]. There are some interesting items that come out of a simple test here:&lt;/p&gt;
&lt;p&gt;DNS query is also available via QUIC / HTTP3. Which means TLS1.3 goodness over UDP or TCP&lt;/p&gt;
&lt;p&gt;cache-control header response value matched the TTL of the DNS record, however if run many times showed wildly variying times, appears to be some caching issue or something along these line - a little more digging (see what I did there) into this is going to be needed.&lt;/p&gt;
&lt;p&gt;I used jq (third-party) to help prettify the JSON output
(Cloudflare)[&lt;a href=&quot;https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/&quot;&gt;https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/&lt;/a&gt;] has an implmentation that allows for both JSON and DNS wire format. I noticed whilst curling the cache-control mirrored the DNS record TTL and wasn’t all over the place as with the Google tests (ie TTL counted down as you’d expect for bog (udp, port 53) standard DNS queries) [b].&lt;/p&gt;
&lt;p&gt;Suffice to say the change to use DOH will require some further consideration before implmeneting. But I believe overall that this is a step in the right direction (to secure DNS communications) that can be easily adopted however I guess time will tell. Been fun playing with this! I found that when testing CloudFlares 1.1.1.1 Andriod App that DNS latency performance for DOH was notibly faster than DOT, but more on that later.&lt;/p&gt;
&lt;p&gt;As a side note about no zero days; whilst I may not post every day I am working on such posts over a number of days. I may change this approach, but this is working for now :)&lt;/p&gt;
&lt;p&gt;[a] Google Query:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl -v https://dns.google.com/resolve?name=www.news24.com -H &quot;Origin: www.someorigin.com&quot; | jq
....
&gt; GET /resolve?name=www.news24.com HTTP/1.1
&gt; Host: dns.google.com
...
&gt; Origin: www.someorigin.com
&gt; 
 GET /dns-query?name=www.news24.com&amp;amp;type=A HTTP/1.1
&gt; Host: cloudflare-dns.com
&gt; User-Agent: curl/7.54.0
&gt; accept: application/dns-json
&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[working with maxmind geoip]]></title><description><![CDATA[scripting querys against the maxmind db’s with python There comes a time when one needs to check for an IP’s likely physical location, in my…]]></description><link>https://etiennemunnich.github.io/working-with-maxmind-geoip/</link><guid isPermaLink="false">https://etiennemunnich.github.io/working-with-maxmind-geoip/</guid><pubDate>Sat, 20 Apr 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;scripting querys against the maxmind db’s with python&lt;/p&gt;
&lt;p&gt;There comes a time when one needs to check for an IP’s likely physical location, in my case I’ve been playing with DNS of HTTPS and DNS over TLS and part of the workflow I had whilst testing was to check the responses GEO location against the free Maxmind database, but more on that another time.&lt;/p&gt;
&lt;p&gt;So I downloaded the GeoLite2 (Free) City + ASN Databases from maxmind, install the prereq’s via pip and built a simple python script to test.&lt;/p&gt;
&lt;p&gt;Found maxmind’s project maxmind (on github) that made building the script easier:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;code&quot;&gt;&lt;pre class=&quot;language-code&quot;&gt;&lt;code class=&quot;language-code&quot;&gt;pip3 install geoip2 --user
brew install libmaxminddb
import geoip2.database
import json

# This creates a Reader object. You should use the same object
# across multiple requests as creation of it is expensive.
reader = geoip2.database.Reader(&amp;#39;./GeoLite2-City_20190416/GeoLite2-City.mmdb&amp;#39;)
reader2 = geoip2.database.Reader(&amp;#39;/./GeoLite2-ASN_20190416/GeoLite2-ASN.mmdb&amp;#39;)

# Replace &amp;quot;city&amp;quot; with the method corresponding to the database
# that you are using, e.g., &amp;quot;country&amp;quot;.
ip = &amp;#39;72.163.4.185&amp;#39;
response = reader.city(ip)
response2 = reader2.asn(ip)

output = {
    &amp;quot;IP&amp;quot;:ip, 
    &amp;quot;Details&amp;quot;:
    [
        {&amp;quot;ISO&amp;quot;:response.country.iso_code}, 
        {&amp;quot;Country&amp;quot;:response.country.name}, 
        {&amp;quot;City&amp;quot;:response.city.name},
        {&amp;quot;ASN&amp;quot;:response2.autonomous_system_number}
        ]
    }

print (json.dumps(output, indent=4))

reader.close()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item></channel></rss>