<?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" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[The Network Stack]]></title><description><![CDATA[practical network tips/design/code]]></description><link>https://thenetworkstack.com/</link><image><url>https://thenetworkstack.com/favicon.png</url><title>The Network Stack</title><link>https://thenetworkstack.com/</link></image><generator>Ghost 5.54</generator><lastBuildDate>Mon, 06 Apr 2026 20:03:46 GMT</lastBuildDate><atom:link href="https://thenetworkstack.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[AWS Session Manager - Zero Trust Access]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>When working with AWS, there are plenty of features that make your life easier, but it&apos;s rare to find a feature that feels like magic...</p>
<p>Before we dive into the magic, what&apos;s the problem we&apos;re trying to solve? When working with servers anywhere, usually</p>]]></description><link>https://thenetworkstack.com/aws-session-manager-zero-trust-access/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28ea</guid><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Mon, 16 Mar 2020 00:10:04 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>When working with AWS, there are plenty of features that make your life easier, but it&apos;s rare to find a feature that feels like magic...</p>
<p>Before we dive into the magic, what&apos;s the problem we&apos;re trying to solve? When working with servers anywhere, usually there needs to be some sort of remote access to SSH or RDP and install/troubleshoot things as needed. Worst case, your server has a public IP with port 22 (SSH) open to the world, which means theoretically anyone, anywhere in the world could break in. As you get more advanced, you setup VPN tunnels or bastion hosts to secure your remote access. This can increase in complexity very quickly with multiple VPC&apos;s across multiple regions, multipied by each AWS account. And with the rise in &quot;Zero Trust&quot; networking, how do you securely provide access without blindly trusting network CIDR&apos;s?</p>
<p>Enter AWS Systems Manager Session Manager. While not a very magical name, it does provide a magical experience. Session Manager gives you remote access to your servers without opening any ports in security groups, building any VPN tunnels, or using bastion hosts. All access is based on IAM permissions, and sessions are proxied by AWS Systems Manager. You can either use the AWS Console for web access, or the AWS CLI for a native &quot;terminal&quot; experience.</p>
<p><strong>What are the requirements?</strong><br>
The <a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-getting-started.html?ref=thenetworkstack.com">official documentation</a> has the most detail, but the short answer is:</p>
<ol>
<li>Verify SSM agent is running on your EC2 instances with an Instance Role that gives access to Systems Manager</li>
<li>If you&apos;re using a local terminal:<br>
a. Verify <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html?ref=thenetworkstack.com">AWS CLI 1.16.12</a> or later is installed<br>
b. Install the <a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html?ref=thenetworkstack.com">Session Manager Plugin for AWS CLI</a></li>
</ol>
<p>Once the requirements are met, you can view your managed instances by going to <em>Systems Manager</em> -&gt; <em>Managed Instances</em> in the AWS Console. You can easily start a web-based session by clicking an Instance and then clicking <em>Actions</em> -&gt; <em>Start Session</em>. The same thing can be accomplished from the EC2 console by clicking your instance and then <em>Connect</em> -&gt; <em>Connection Method: Session Manager</em>. While this feels similar to other tools (like a VMware console), the real magic is using the terminal on your local computer.</p>
<p>You can start a remote &quot;SSH&quot; style session with your instances that have zero inbound access with this command:</p>
<pre><code class="language-bash">$ aws ssm start-session --target instance_id
</code></pre>
<p>At this point, you have SSH access to your instance, and can go through all your normal installation or troubleshooting steps. The first time you do this feels like magic, as you realize all the time you no longer need to spend with VPN tunnels, bastion hosts, and opening up security groups for remote access.</p>
<p><strong>But wait, there&apos;s more!</strong> Not only can you initiate remote access sessions for SSH or Powershell, but SSM can also do <a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-sessions-start.html?ref=thenetworkstack.com">port-forwarding</a> from your local computer to the remote server! Want to see what a particular web-server is showing on port 80? Just forward a random local port (ex. 9999) to your web-server port 80, and then navigate to <a href="http://localhost:9999/?ref=thenetworkstack.com">http://localhost:9999</a> in your web-browser. How about Windows RDP access? Session manager only supports SSH or Powershell for remote sessions, but with the port-forwarding feature, we can also get remote RDP access:</p>
<pre><code class="language-bash">$ aws ssm start-session --target instance_id --document-name AWS-StartPortForwardingSession --parameters portNumber=&quot;3389&quot;,localPortNumber=&quot;33389&quot;
</code></pre>
<p>Since the &quot;localPortNumber&quot; is set to 33389 above, you would just RDP to 127.0.0.1:33389 to port-forward to your remote instance.</p>
<p>Ok, at this point AWS has provided zero trust remote access, but remembering the AWS CLI SSM commands (especially port-forwarding) aren&apos;t the most intuitive. Also, getting the EC2 instance id requires going back and forth between your terminal the AWS web console. I decided to write a Python script that abstracts some of complexity while making it easy to start remote sessions and port-fowarding.</p>
<p>I&apos;ve called this script <strong>AWS Remote</strong>: <a href="https://github.com/dkuchenski/aws-remote?ref=thenetworkstack.com">https://github.com/dkuchenski/aws-remote</a></p>
<p>Some of the main features of AWS Remote:</p>
<ul>
<li>Listing all EC2 instance ids, important attributes, and SSM management status</li>
<li>Start remote sessions via instance id or instance name</li>
<li>Friendly port-forward syntax via instance id or instance name</li>
</ul>
<p>So instead of remembering the AWS CLI syntax and finding instance id&apos;s, you can do this:</p>
<pre><code class="language-bash">$ aws-remote session instance2-example.domain.com
</code></pre>
<p>or</p>
<pre><code>$ aws-remote port-forward 8080 80 instance2-example.domain.com
</code></pre>
<p><em>Note: The instance &quot;name&quot; is referencing the Name tag of the instance</em></p>
<p>This script uses a combination of the Python Boto3 SDK and the AWS CLI to get information from AWS and start sessions based on your parameters. This is also the first time I&apos;ve used <a href="https://click.palletsprojects.com/en/7.x/?ref=thenetworkstack.com">Click</a> to build the command line interface. Click is great for building easy to use CLI&apos;s, and therefore you can use <code>--help</code> at any point to see what your available options are. I&apos;ve also mimicked the AWS CLI <code>--profile</code> and <code>--region</code> options for a familiar setup.</p>
<pre><code class="language-bash">$ aws-remote --help
Usage: aws-remote [OPTIONS] COMMAND [ARGS]...

  AWS Remote is a simple, command line tool to view and interact with AWS
  instances via SSM. Requires the AWS CLI and Session Manager Plugin to be
  installed locally.

Options:
  --profile TEXT  Specify AWS profile
  --region TEXT   Specify AWS region
  --help          Show this message and exit.

Commands:
  list          List EC2 instances and SSM management status
  port-forward  Start SSM port forward to instance id/name
  session       Start SSM session with instance id/name
</code></pre>
<p>I&apos;m still figuring out the best way to distribute scripts like this, but for now there are a couple installation steps that can be found here: <a href="https://github.com/dkuchenski/aws-remote/blob/master/README.md?ref=thenetworkstack.com">https://github.com/dkuchenski/aws-remote/blob/master/README.md</a></p>
<p>Hope AWS Remote is a useful tool, and if you have any feedback, please let me know!</p>
<br>
<br>
<br>
<p>Amazon Blog about Session Manager:<br>
<a href="https://aws.amazon.com/blogs/aws/new-session-manager/?ref=thenetworkstack.com">https://aws.amazon.com/blogs/aws/new-session-manager/</a></p>
<p>References for using Click in a Python CLI:<br>
<a href="https://dbader.org/blog/mastering-click-advanced-python-command-line-apps?ref=thenetworkstack.com">https://dbader.org/blog/mastering-click-advanced-python-command-line-apps</a><br>
<a href="https://stackoverflow.com/questions/23626972/how-do-i-pass-variables-to-other-methods-using-pythons-click-command-line-inte?ref=thenetworkstack.com">https://stackoverflow.com/questions/23626972/how-do-i-pass-variables-to-other-methods-using-pythons-click-command-line-inte</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[AWS Transit Gateway]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>At re:Invent 2018, AWS announced the Transit Gateway, finally giving us a native solution to provide scalable transit connectivity. After attending sessions and deploying Transit Gateway, I wanted to dive into the solution and see what is possible.</p>
<br>
<h4 id="techspecs"><strong>Tech Specs</strong></h4>
<p>In case you haven&apos;t read the <a href="#preofficialdocs">official</a></p>]]></description><link>https://thenetworkstack.com/aws-transit-gateway/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e9</guid><category><![CDATA[aws]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Fri, 30 Nov 2018 16:28:22 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>At re:Invent 2018, AWS announced the Transit Gateway, finally giving us a native solution to provide scalable transit connectivity. After attending sessions and deploying Transit Gateway, I wanted to dive into the solution and see what is possible.</p>
<br>
<h4 id="techspecs"><strong>Tech Specs</strong></h4>
<p>In case you haven&apos;t read the <a href="#preofficialdocs">official docs</a>, the AWS Transit Gateway is a regional layer3 router connecting VPC, VPN, Direct Connect (soon) across multiple accounts, with support for multiple route tables (VRFs). The Transit Gateway (TGW) has <em>much</em> higher scalability limits than VPC peering.</p>
<p><img src="https://thenetworkstack.com/content/images/2018/11/tgw-limits.png" alt="tgw-limits" loading="lazy"></p>
<p><em>How did Amazon put a big router in the cloud?</em><br>
The Transit Gateway is part of the AWS Hyperplane architecture, an internal AWS service that provides terabits of capacity. This is tested and proven tech, already powering NLB, NAT Gateway, and EFS:</p>
<p><img src="https://thenetworkstack.com/content/images/2018/11/tgw-hyperplane.jpg" alt="tgw-hyperplane" loading="lazy"></p>
<br>
<h4 id="configuration"><strong>Configuration</strong></h4>
<p>To setup a TGW, log into your AWS account, and go to VPC. When you click &quot;Create Transit Gateway&quot;, you&apos;ll be greeted with this screen:</p>
<p><img src="https://thenetworkstack.com/content/images/2018/11/tgw-create.png" alt="tgw-create" loading="lazy"></p>
<p>There are a couple options that weren&apos;t immediately clear to me, so lets go through them all:</p>
<ul>
<li><strong>Name tag:</strong> Up to you, I use $accountName-$region-tgw</li>
<li><strong>Description:</strong> ^</li>
<li><strong>Amazon side ASN:</strong> Depends on your routing policy, I use a unique private ASN per TGW for routing policy flexibility</li>
<li><strong>DNS support:</strong> Allows private DNS resolution across VPCs, I would keep this checked</li>
<li><strong>VPN ECMP support:</strong> A single VPN connection is limited to 1.25Gbps, so enable ECMP and use multiple VPN connections to aggregate VPN throughput. AWS has tested up to 50Gbps successfully with ECMP, but theoretically there is &quot;no limit&quot;.</li>
<li><strong>Default route table association:</strong> Automatically associate attachments with the default route table. For example, when you attach a VPC to the TGW, use the default route table. This depends on how you use route tables, but I would keep this checked.</li>
<li><strong>Default route table propagation:</strong> Automatically propogate routes from attachments into the default route table. This will allow anything connected to the default route table to route to each other (assuming the VPC route table is also configured). Depending on how you use the TGW, you may not want this. If you do not want spoke-to-spoke connectivity, do not check this.</li>
<li><strong>Auto accept shared attachments:</strong> Automatically accept cross-account attachments to your VPC. I would leave this unchecked.</li>
</ul>
<p><em>CAUTION</em>: You <strong>cannot</strong> change the above values later. You would need to create a new TGW.</p>
<p>Once your TGW is created, you need to &quot;attach&quot; it to a VPC or VPN connection. For VPN, this should look familiar, as you use BGP or static routing to connect to a customer gateway. For VPC, things start to deviate from previous transit solutions. First, you must select VPC subnets in every AZ that you plan to use. This provisions an ENI in those subnets that the TGW then uses to route traffic to that AZ. <em>You can only select one subnet per AZ.</em> <strong>This does not affect routing to other subnets in the AZ</strong>, its just what the TGW uses to route to that AZ. Then, you manually add routes in the route table that point to the TGW target. The VPC route table limits have not changed (50 route default, 100 route max), so it is best practice to use a summary route to the TGW. I would just route the RFC1918 address ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to the TGW, and then any VPC peering you may do will still work with a more specific route.</p>
<p>Once the TGW is attached to your VPCs, you then need to associate the attachment with a route table, and propopage routes into the route table. If you left all the default options when creating the TGW, both of these actions are done automatically. This provides <em>flat</em>, any-to-any VPC routing out of the box.</p>
<p><img src="https://thenetworkstack.com/content/images/2018/11/tgw-any.jpg" alt="tgw-any" loading="lazy"></p>
<p>If you are looking for <em>isolated</em> hub-and-spoke routing (prevent spokes from talking), then we need to change our config:</p>
<ol>
<li>Create a new TGW route table (VRF) for your hub location, which could be another VPC or VPN</li>
<li>Associate the hub attachment with the TGW hub route table</li>
<li>Propagate the spoke routes into the TGW hub route table</li>
<li>Propagate the hub routes into the TGW default route table, used by the spokes</li>
<li>If the default route table has all the spoke routes present, delete those. You can always add routes back if needed. This prevents the spokes from routing to each other, while still allowing access to the hub.</li>
</ol>
<p><img src="https://thenetworkstack.com/content/images/2018/11/tgw-isolated.jpg" alt="tgw-isolated" loading="lazy"></p>
<p>Finally, since TGW is a regional service, how do you connect multiple regions? Right now, this would be done with a transit VPC, or an on-premise router. But if you can wait until early 2019, AWS should have a native solution!</p>
<p><img src="https://thenetworkstack.com/content/images/2018/11/tgw-multiregion.jpg" alt="tgw-multiregion" loading="lazy"></p>
<p><a name="preofficialdocs"></a></p>
<p>To summarize, the two architectures discussed here were:</p>
<ol>
<li><strong>Flat, any-to-any connectivity.</strong> Achieved with the default TGW configuration. All associations and propagations go into the default route table.</li>
<li><strong>Isolated, hub-and-spoke connectivity.</strong> Requires another route table for the hub, and changing route propagation so the spokes only see the hubs route. The hub route table should have propagated routes from all the spokes.</li>
</ol>
<p>AWS Transit Gateway is a great addition to the AWS networking stack, and really provides a extremely scalable, secure solution for routing in the cloud.</p>
<br>
<hr>
<br>
<h4 id="officialdocs"><strong>Official Docs</strong></h4>
<p><a href="https://aws.amazon.com/about-aws/whats-new/2018/11/introducing-aws-transit-gateway/?ref=thenetworkstack.com">Introducing AWS Transit Gateway</a><br>
<a href="https://aws.amazon.com/transit-gateway/?ref=thenetworkstack.com">AWS Transit Gateway Solution</a><br>
<a href="https://docs.aws.amazon.com/vpc/latest/tgw/what-is-transit-gateway.html?ref=thenetworkstack.com">AWS Transit Gateway Docs</a></p>
<br>
<h4 id="updateawshaspostedalltheslidesfromthenet402session"><strong>Update:</strong> AWS has posted all the slides from the NET402 session</h4>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/zDwhn3Fj4nxlcd" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/AmazonWebServices/new-launch-aws-transit-gateway-and-transit-vpcs-reference-architectures-for-many-vpcs-net402-aws-reinvent-2018" title="[NEW LAUNCH!] AWS Transit Gateway and Transit VPCs - Reference Architectures for Many VPCs (NET402) - AWS re:Invent 2018" target="_blank">[NEW LAUNCH!] AWS Transit Gateway and Transit VPCs - Reference Architectures for Many VPCs (NET402) - AWS re:Invent 2018</a> </strong></div><!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[AWS Certified Advanced Networking in 20 Days]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Can the AWS Certified Advanced Networking Specialty exam be legitemately passed with only a few weeks of studying? <strong>Yes.</strong></p>
<p>Is there a secret shortcut? <strong>No.</strong></p>
<p>Although there is no shortcut, I will discuss my <strong>previous experience</strong>, <strong>study materials</strong>, and <strong>general impressions</strong> of the exam. If you have already been working</p>]]></description><link>https://thenetworkstack.com/aws-certified-advanced-networking-in-20-days/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e8</guid><category><![CDATA[aws]]></category><category><![CDATA[ans]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Mon, 12 Nov 2018 15:06:52 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Can the AWS Certified Advanced Networking Specialty exam be legitemately passed with only a few weeks of studying? <strong>Yes.</strong></p>
<p>Is there a secret shortcut? <strong>No.</strong></p>
<p>Although there is no shortcut, I will discuss my <strong>previous experience</strong>, <strong>study materials</strong>, and <strong>general impressions</strong> of the exam. If you have already been working with AWS networking, and wondering what it takes to be certified, this post should give you a pretty good idea. Regarding my timeline, I passed the AWS Certified Solutions Architect Associate exam on 10/18/18, and then passed the AWS Certified Advanced Networking Specialty exam twenty days later on 11/7/18.<br>
<br></p>
<h4 id="1previousexperience"><strong>1. Previous Experience</strong></h4>
<p>First, I&apos;ve worked in &quot;traditional&quot; networking before starting my AWS experience, and have passed the Cisco CCNP and CCDP exams. This is a huge advantage if you are looking to take the AWS Certified Advanced Network Specialty exam (ANS), since the <a href="https://d1.awsstatic.com/training-and-certification/eligibilityupdates/AWS%20Certified%20Advanced%20Networking%20-%20Speciality_Exam_Guide_v1.2_FINAL.pdf?ref=thenetworkstack.com">exam guide</a> recommends the following &quot;General IT Knowledge&quot;:</p>
<ul>
<li>Advanced networking architectures and interconnectivity options (e.g., IP VPN, MPLS/VPLS)</li>
<li>Networking technologies within the OSI model, and how they affect implementation decisions</li>
<li>Development of automation scripts and tools
<ul>
<li>Routing architectures (including static and dynamic)</li>
<li>Multi-region solutions for a global enterprise</li>
<li>Highly available connectivity solutions (e.g., DX, VPN)</li>
</ul>
</li>
<li>CIDR and sub-netting (IPv4 and IPv6)</li>
<li>IPv6 transition challenges</li>
<li>Generic solutions for network security features, including WAF, IDS, IPS, DDoS protection, and Economic Denial of Service/Sustainability (EDoS).</li>
</ul>
<p>90% of those topics are covered by the CCNP, and if you have worked in an enterprise environment, you have probably seen or used similar network security features listed on the last line.</p>
<p>Second, I have been working with AWS networking for about 4 years. This started out small, troubleshooting a security group, or creating a vpc, and growing to designing multi-account, multi-region network services and connectivity. This was supplemented by the knowledge I recently gained studying for and taking the AWS SAA exam. Even though an associate exam is no longer required to take a specialty exam, I would highly recommend it, so you can learn the AWS way of doing things &quot;right&quot;.<br>
<br></p>
<h4 id="2studymaterials"><strong>2. Study Materials</strong></h4>
<p>Even with the experience described above, I did not immediately go and take the exam. For me, passing the exam isn&apos;t just filling in the correct answer, its learning the AWS approach to solving problems, and all the available solutions. I used two main resources to study for the exam:</p>
<ul>
<li>Linux Academy <a href="https://linuxacademy.com/amazon-web-services/training/course/name/aws-certified-networking-specialty?ref=thenetworkstack.com">Online Course</a></li>
<li>The AWS Certified Advanced Networking <a href="https://www.amazon.com/Certified-Advanced-Networking-Official-Study/dp/1119439833/?ref=thenetworkstack.com">Official Study Guide</a></li>
</ul>
<p>After using Linux Academy for the SAA exam, I was excited to try their ANS cource. Unfortunately I wasn&apos;t as impressed, maybe because I was already familiar with the material, but there also weren&apos;t as many labs, and the quizes towards the end felt lazy with only a couple questions each. Overall, I did find the material useful and mostly listened to the instructor at 1.25x or 1.5x speed while taking notes on important points. I still recommend Linux Academy as a general training resource, since I&apos;m a fan of their on-demand labs and wide range of content.</p>
<p>If you are looking to get the most bang for your buck, I would definitely purchase the official study guide. The guide is written by seven AWS Solutions Architects, and I found the content very thorough. At the end of every chapter are resources to review, exam essentials, exercises and review questions. The book also includes online practice exams and flashcards. I recommend taking the practice exams over and over again until you genuinely understand each question and the correct answer.</p>
<p>Last, AWS provides whitepapers and various documentation that can also be used as study material. Near the end of my studying I also found more content on <a href="https://aws.amazon.com/answers/networking/?ref=thenetworkstack.com">AWS Answers</a>. For example, these articles on network connectivity:</p>
<ul>
<li><a href="https://aws.amazon.com/answers/networking/aws-multiple-data-center-ha-network-connectivity/?ref=thenetworkstack.com">Multiple Data Center HA Network Connectivity</a></li>
<li><a href="https://aws.amazon.com/answers/networking/aws-single-data-center-ha-network-connectivity/?ref=thenetworkstack.com">Single Data Center HA Network Connectivity</a><br>
<br></li>
</ul>
<h4 id="3generalimpressions"><strong>3. General Impressions</strong></h4>
<p>I thought this was a difficult test. It isn&apos;t enough to know one solution to a given scenario. AWS expects you to know every solution to a scenario, the benefits and limits of each solution, and be able determine the best solution <em>for the scenario</em>. <strong>You need to deep dive into each subject</strong>. There were still times that I didn&apos;t 100% know the answer that AWS was looking for, and I had to make an educated guess. I think &quot;Domain 5.0: Design and implement for security and compliance&quot; from the <a href="https://d1.awsstatic.com/training-and-certification/eligibilityupdates/AWS%20Certified%20Advanced%20Networking%20-%20Speciality_Exam_Guide_v1.2_FINAL.pdf?ref=thenetworkstack.com">exam guide</a> was my biggest challenge. Unfortunately I can&apos;t go into more detail, as I don&apos;t want to risk violating the <a href="https://aws.amazon.com/certification/certification-agreement/?ref=thenetworkstack.com">exam agreement</a>. I am proud to have passed the AWS ANS exam, and I think it is worth pursuing if you work with AWS networking frequently.</p>
<p>Hopefully this post was helpful, if you&apos;d like to discuss AWS networking, come find me at re:Invent 2018! I can be reached via <a href="https://twitter.com/DanielKuchenski?ref=thenetworkstack.com">Twitter</a>.<br>
<br></p>
<p><img src="https://thenetworkstack.com/content/images/2018/11/aws-ans-small.png" alt="aws-ans-small" loading="lazy"></p>
<p>PS. I also discovered a couple other blog posts with some amazing study content after I had already passed the exam:</p>
<p><a href="https://blog.ashiny.cloud/2018/07/29/aws-certified-advanced-networking-specialty/?ref=thenetworkstack.com">https://blog.ashiny.cloud/2018/07/29/aws-certified-advanced-networking-specialty/</a></p>
<p><a href="https://www.itdiversified.com/aws-certified-advanced-networking-prep-direct-connect/?ref=thenetworkstack.com">https://www.itdiversified.com/aws-certified-advanced-networking-prep-direct-connect/</a><br>
<a href="https://www.itdiversified.com/aws-certified-advanced-networking-prep-vpc/?ref=thenetworkstack.com">https://www.itdiversified.com/aws-certified-advanced-networking-prep-vpc/</a><br>
<a href="https://www.itdiversified.com/aws-certified-advanced-networking-prep-vpn/?ref=thenetworkstack.com">https://www.itdiversified.com/aws-certified-advanced-networking-prep-vpn/</a><br>
<a href="https://www.itdiversified.com/aws-certified-advanced-networking-prep-route-53/?ref=thenetworkstack.com">https://www.itdiversified.com/aws-certified-advanced-networking-prep-route-53/</a></p>
<p><a href="https://www.whizlabs.com/blog/aws-certified-advanced-networking-specialty-certification-preparation/?ref=thenetworkstack.com">https://www.whizlabs.com/blog/aws-certified-advanced-networking-specialty-certification-preparation/</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Ansible 2.5 - New Network Modules]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Ansible 2.5 just came out, and with it comes new network modules (and the network_cli and netconf connectivity methods). The new modules allow us to manage certain IOS configurations without always depending on the &quot;ios_config&quot; module, while the network_cli connectivity method means we don&</p>]]></description><link>https://thenetworkstack.com/ansible-2-5-new-network-modules/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e6</guid><category><![CDATA[ansible]]></category><category><![CDATA[cisco]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Mon, 26 Mar 2018 14:25:52 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Ansible 2.5 just came out, and with it comes new network modules (and the network_cli and netconf connectivity methods). The new modules allow us to manage certain IOS configurations without always depending on the &quot;ios_config&quot; module, while the network_cli connectivity method means we don&apos;t always need to configure a &quot;provider&quot; for every network playbook. These new modules and connectivity methods allow networking configuration management to look and feel similar to our server management playbooks, which is great for cross-functional teams and reusability.</p>
<blockquote>
<p><strong>Ansible 2.5 Release Info:</strong><br>
<a href="https://www.ansible.com/blog/coming-soon-networking-features-in-ansible-2.5?ref=thenetworkstack.com">New Networking Features in Ansible 2.5</a><br>
<a href="http://docs.ansible.com/ansible/devel/modules/list_of_network_modules.html?ref=thenetworkstack.com">List of All Network Modules in Ansible 2.5</a><br>
<a href="http://docs.ansible.com/ansible/devel/network/user_guide/network_best_practices_2.5.html?ref=thenetworkstack.com">Network Best Practices for Ansible 2.5</a></p>
</blockquote>
<p>For a quick introduction, I&apos;m going to take my previously discussed <a href="https://thenetworkstack.com/ansible-vlan-provisioning/">VLAN provisioning playbook</a> and convert it to Ansible 2.5 syntax.</p>
<p>First, remember to upgrade to Ansible 2.5. If you have already have <a href="https://thenetworkstack.com/ansible-installation/">ansible installed</a>, then just upgrade with:</p>
<pre><code class="language-no-highlight">apt-get update &amp;&amp; apt-get install ansible
</code></pre>
<br>
<p>Our first major change is going to use &quot;group_vars&quot; to define connection settings for our network devices. By default, Ansible will read any variable in <mark>group_vars/all.yml</mark>, <mark>group_vars/&lt;group_name&gt;</mark> and <mark>host_vars/&lt;host_name&gt;</mark> when a playbook is executed.  Since we are defining how to connect to <strong>all</strong> our Cisco IOS devices, I am going to put our connection variables in <strong>groups_vars/ios-switches.yml</strong></p>
<pre><code class="language-no-highlight">ansible_connection: network_cli
ansible_network_os: ios
ansible_user: ciscoadmin
ansible_ssh_pass: cisco123
</code></pre>
<p>To use the network_cli connection, you must specify the &quot;ansible_network_os&quot;. Also, please <strong>do not</strong> store your password in plain-text and instead use Ansible Vault, but to keep this example simple, we are using the password &quot;cisco123&quot;.</p>
<p>Since our &quot;ansible_connection&quot; is defined in group_vars, we no longer need the &quot;connection: local&quot; parameter in our playbook.</p>
<p>Next, instead of using the &quot;ios_config&quot; module to create and name VLAN&apos;s, let&apos;s use the new <strong>ios_vlan</strong> module.</p>
<pre><code class="language-no-highlight">---
- hosts: ios-switches
  vars:
    vlan_id: 998
    vlan_name: Ansible_VLAN
    
tasks:
    - name: Provision VLAN
      ios_vlan:
        vlan_id: &quot;{{ vlan_id }}&quot;
        name: &quot;{{ vlan_name }}&quot;
        state: present

    - name: Show VLAN
      ios_command:
        commands: show vlan brief
      register: show_vlan

    - debug: var=show_vlan.stdout_lines
</code></pre>
<p>As you can see the <strong>ios_vlan</strong> module simplifies our VLAN provisioning process, since we can define the VLAN ID and the VLAN NAME in a single task. The &quot;state&quot; of the VLAN is not required to create a VLAN, but I included it to show how the new modules use declaritive statements to make creating/removing configuration easier.  If we want to remove a VLAN, just change the &quot;state&quot; to <strong>absent</strong>. I also left in our &quot;show vlan&quot; task from last time, so we can verify our configuration change without logging into the switch manually.</p>
<p>Now to run the playbook:</p>
<pre><code>root@ubuntu:/etc/ansible# ansible-playbook network_new-vlan.yml

PLAY [ios-switches] *************************************************************************************************************************************

TASK [Provision VLAN] ***********************************************************************************************************************************
changed: [10.170.200.2]

TASK [Show VLAN] ****************************************************************************************************************************************
ok: [10.170.200.2]

TASK [debug] ********************************************************************************************************************************************
ok: [10.170.200.2] =&gt; {
    &quot;show_vlan.stdout_lines&quot;: [
        [
            &quot;VLAN Name                             Status    Ports&quot;,
            &quot;---- -------------------------------- --------- -------------------------------&quot;,
            &quot;1    default                          active    Gi0/10, Gi0/11, Gi0/12&quot;,
            &quot;10   FW_VLAN                          active    Gi0/3, Gi0/4, Gi0/5, Gi0/6, Gi0/7&quot;,
            &quot;20   Data_VLAN                        active    Gi0/1, Gi0/2&quot;,
            &quot;30   Voice_VLAN                       active    Gi0/1, Gi0/2, Gi0/3, Gi0/4, Gi0/5, Gi0/6, Gi0/7&quot;,
            &quot;998  Ansible_VLAN                     active    &quot;,
            &quot;1002 fddi-default                     act/unsup &quot;,
            &quot;1003 token-ring-default               act/unsup &quot;,
            &quot;1004 fddinet-default                  act/unsup &quot;,
            &quot;1005 trnet-default                    act/unsup&quot;
        ]
    ]
}

PLAY RECAP **********************************************************************************************************************************************
10.170.200.2                : ok=4    changed=1    unreachable=0    failed=0
</code></pre>
<p>Success!! While this is great for individual VLAN changes, the real power comes when you define all your environment VLAN&apos;s in group_var or host_var files, and looping through the &quot;ios_vlan&quot; task for every VLAN required.  I&apos;ll save that for a future post!</p>
<p>You can find this playbook (including ansible.cfg and directory structure) on my github: <a href="https://github.com/dkuchenski/thenetworkstack-ansible/tree/master/vlan-provisioning-2.5?ref=thenetworkstack.com">https://github.com/dkuchenski/thenetworkstack-ansible/tree/master/vlan-provisioning-2.5</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Optimize Ruckus Configuration - Part 2]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A couple years ago I posted how to <a href="https://thenetworkstack.com/optimize-ruckus-configuration/">Optimize Ruckus Configuration</a>, and since then I&apos;ve been continually tweaking so that my dense, multi-story WiFi environment performs well with Windows, Mac OSX, and mobile devices.  Here are my current optimizations:</p>
<p><em>Note: This is based on Ruckus ZoneDirector 10.0.</em></p>]]></description><link>https://thenetworkstack.com/optimize-ruckus-configuration-part-2/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e5</guid><category><![CDATA[ruckus]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Mon, 19 Feb 2018 16:56:50 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A couple years ago I posted how to <a href="https://thenetworkstack.com/optimize-ruckus-configuration/">Optimize Ruckus Configuration</a>, and since then I&apos;ve been continually tweaking so that my dense, multi-story WiFi environment performs well with Windows, Mac OSX, and mobile devices.  Here are my current optimizations:</p>
<p><em>Note: This is based on Ruckus ZoneDirector 10.0.1.0 build 44</em></p>
<p><strong>System Wide:</strong></p>
<ul>
<li>Channel Optimization: Optimize for Performance. This enables all the 5GHz channels, which is especially useful in a dense environment.</li>
<li>Self-Healing: Automatically adjust 2.4Ghz and 5Ghz channels using Background scanning (I found ChannelFly too busy)</li>
<li>Background Scanning: Run a background scan every 3600 seconds. The default is too short, causing unnecessary channel changes.</li>
</ul>
<p><strong>AP Specific:</strong></p>
<ul>
<li>Radio B/G/N(2.4G): Only allows channels 1, 6, 11</li>
<li>Radio A/N/AC(5G) Indoor: Depending on the environment, I may allow all, or disable certain DFS channels or Apple TV peer-to-peer channel (149).</li>
<li>Channelization 2.4GHz: 20</li>
<li>Channelization 5.0GHz: 40 (80 just uses too many channels in a dense environment)</li>
<li>I also disable the 2.4GHz radio on approximately every other AP, since AP placement is built for 5GHz coverage. This helps with 2.4GHz channel contention.</li>
<li>Turn down TX power for 2.4GHz radios, and potentially 5GHz radios depending on placement.</li>
</ul>
<p><strong>WLAN Specific:</strong></p>
<ul>
<li>If wireless clients do not need to communicate directly with each other (less common with everything &quot;cloud&quot;), enable Wireless client isolation.</li>
<li>We want Band Balancing, so uncheck &quot;Do not perform Band Balancing on this WLAN service&quot;</li>
<li>Enable OFDM Only (Disable legacy 802.11b only clients)</li>
<li>BSS Min Rate: 24.00mbps (Encourages roaming to closer AP)</li>
<li>Enable 802.11k</li>
</ul>
<p>With these changes, I have little complaints from users, and wireless &quot;just works&quot;. Of course, Apple clients (particulary OSX) are the most difficult, but most of their problems can be solved by turning their WiFi off/on, or sometimes resetting PRAM.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[AWS - CloudFormation - Create VPC]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>If you have worked with AWS networking, you know there is a laundry list of items that need to be initally configured so the environment is ready for use:</p>
<ul>
<li>VPC</li>
<li>Internet Gateway</li>
<li>VPN Gateway</li>
<li>Public Subnets</li>
<li>Private Subnets</li>
<li>Public Route Tables</li>
<li>Private Route Tables</li>
<li>NAT Gateways</li>
<li><em>and more depending on</em></li></ul>]]></description><link>https://thenetworkstack.com/aws-cloudformation-create-vpc/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e4</guid><category><![CDATA[aws]]></category><category><![CDATA[cloudformation]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Sat, 27 Jan 2018 20:14:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>If you have worked with AWS networking, you know there is a laundry list of items that need to be initally configured so the environment is ready for use:</p>
<ul>
<li>VPC</li>
<li>Internet Gateway</li>
<li>VPN Gateway</li>
<li>Public Subnets</li>
<li>Private Subnets</li>
<li>Public Route Tables</li>
<li>Private Route Tables</li>
<li>NAT Gateways</li>
<li><em>and more depending on your environment</em></li>
</ul>
<p>Since AWS is a software defined cloud datacenter, you will get more and more requests for a <em>Prod environment</em>, then <em>Dev environment</em>, then <em>QA environment</em>, then <em>DevOps environment</em>, etc...but wait, this also needs to be done in <strong>every</strong> region! Instead of spending your time pointing and clicking your way through the AWS GUI, Amazon has provided an infrastructure automation solution called <strong>CloudFormation</strong>. CloudFormation uses the AWS API&apos;s to automate the provisioning of AWS resources, and its very simple to use.</p>
<ol>
<li>Set up your YAML or JSON file that describes your infrastructure</li>
<li>Use the AWS-CLI or GUI to launch (or delete) your infrastructure</li>
</ol>
<p>Luckily AWS has great <a href="https://docs.aws.amazon.com/codebuild/latest/userguide/cloudformation-vpc-template.html?ref=thenetworkstack.com">sample docs</a>, and I have added VPN Gateway parts, extra subnets, and my naming scheme to the code below (also available on my <a href="https://github.com/dkuchenski/thenetworkstack-aws/blob/master/cloudformation-vpc-create.yaml?ref=thenetworkstack.com">github</a>). YAML is easy to read, so feel free to take and change what you need for your environment:</p>
<pre><code class="language-no-highlight">Description: 

    This template deploys a VPC, with three public and private subnets spread 
    across three Availability Zones. It deploys an Internet Gateway, with a default 
    route in the public subnets. It deploys three NAT Gateways (one in each AZ), 
    and default routes for them in the private subnets. It deploys a VPN gateway,
    attaches the gateway to the VPC and enables route propagation in all route tables.

Parameters:
    EnvironmentName:
        Description: An environment name that will be prefixed to resource names
        Type: String
        Default: thenetworkstack
    EnvironmentLocation:
        Description: Name of the AWS region that is being used (ex. us-west-2)
        Type: String
        Default: us-west-2
    VpcCIDR:
        Description: Please enter the IP range (CIDR notation) for this VPC
        Type: String
        Default: 10.64.0.0/19
    PublicSubnet1CIDR:
        Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
        Type: String
        Default: 10.64.0.0/22
    PublicSubnet2CIDR:
        Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone
        Type: String
        Default: 10.64.4.0/22
    PublicSubnet3CIDR:
        Description: Please enter the IP range (CIDR notation) for the public subnet in the third Availability Zone
        Type: String
        Default: 10.64.8.0/22
    PrivateSubnet1CIDR:
        Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
        Type: String
        Default: 10.64.16.0/22
    PrivateSubnet2CIDR:
        Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
        Type: String
        Default: 10.64.20.0/22
    PrivateSubnet3CIDR:
        Description: Please enter the IP range (CIDR notation) for the private subnet in the third Availability Zone
        Type: String
        Default: 10.64.24.0/22
Resources:
    VPC: 
        Type: AWS::EC2::VPC
        Properties:
            CidrBlock: !Ref VpcCIDR
            EnableDnsSupport: True
            EnableDnsHostnames: True
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-vpc
    InternetGateway:
        Type: AWS::EC2::InternetGateway
        Properties:
            Tags:
                - Key: Name
                  Value: !Sub ${EnvironmentName}-igw
    VPNGateway: 
        Type: AWS::EC2::VPNGateway
        Properties: 
            Type: ipsec.1
            Tags: 
                - Key: Name
                  Value: !Sub ${EnvironmentName}-vpg
    InternetGatewayAttachment:
        Type: AWS::EC2::VPCGatewayAttachment
        Properties:
            InternetGatewayId: !Ref InternetGateway
            VpcId: !Ref VPC
    VPNGatewayAttachment:
        Type: AWS::EC2::VPCGatewayAttachment
        Properties:
            VpnGatewayId: !Ref VPNGateway
            VpcId: !Ref VPC
    PublicSubnet1: 
        Type: AWS::EC2::Subnet
        Properties:
            VpcId: !Ref VPC
            AvailabilityZone: !Select [ 0, !GetAZs &apos;&apos; ]
            CidrBlock: !Ref PublicSubnet1CIDR
            MapPublicIpOnLaunch: true
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-public-${EnvironmentLocation}a
    PublicSubnet2: 
        Type: AWS::EC2::Subnet
        Properties:
            VpcId: !Ref VPC
            AvailabilityZone: !Select [ 1, !GetAZs &apos;&apos; ]
            CidrBlock: !Ref PublicSubnet2CIDR
            MapPublicIpOnLaunch: true
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-public-${EnvironmentLocation}b
    PublicSubnet3: 
        Type: AWS::EC2::Subnet
        Properties:
            VpcId: !Ref VPC
            AvailabilityZone: !Select [ 2, !GetAZs &apos;&apos; ]
            CidrBlock: !Ref PublicSubnet3CIDR
            MapPublicIpOnLaunch: true
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-public-${EnvironmentLocation}c
    PrivateSubnet1: 
        Type: AWS::EC2::Subnet
        Properties:
            VpcId: !Ref VPC
            AvailabilityZone: !Select [ 0, !GetAZs &apos;&apos; ]
            CidrBlock: !Ref PrivateSubnet1CIDR
            MapPublicIpOnLaunch: false
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-private-${EnvironmentLocation}a
    PrivateSubnet2: 
        Type: AWS::EC2::Subnet
        Properties:
            VpcId: !Ref VPC
            AvailabilityZone: !Select [ 1, !GetAZs &apos;&apos; ]
            CidrBlock: !Ref PrivateSubnet2CIDR
            MapPublicIpOnLaunch: false
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-private-${EnvironmentLocation}b
    PrivateSubnet3: 
        Type: AWS::EC2::Subnet
        Properties:
            VpcId: !Ref VPC
            AvailabilityZone: !Select [ 2, !GetAZs &apos;&apos; ]
            CidrBlock: !Ref PrivateSubnet3CIDR
            MapPublicIpOnLaunch: false
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-private-${EnvironmentLocation}c
    NatGateway1EIP:
        Type: AWS::EC2::EIP
        DependsOn: InternetGatewayAttachment
        Properties: 
            Domain: vpc
    NatGateway2EIP:
        Type: AWS::EC2::EIP
        DependsOn: InternetGatewayAttachment
        Properties:
            Domain: vpc
    NatGateway3EIP:
        Type: AWS::EC2::EIP
        DependsOn: InternetGatewayAttachment
        Properties:
            Domain: vpc
    NatGateway1: 
        Type: AWS::EC2::NatGateway
        Properties: 
            AllocationId: !GetAtt NatGateway1EIP.AllocationId
            SubnetId: !Ref PublicSubnet1
            Tags:
                - Key: Name
                  Value: !Sub ${EnvironmentName}-${EnvironmentLocation}a
    NatGateway2: 
        Type: AWS::EC2::NatGateway
        Properties:
            AllocationId: !GetAtt NatGateway2EIP.AllocationId
            SubnetId: !Ref PublicSubnet2
            Tags:
                - Key: Name
                  Value: !Sub ${EnvironmentName}-${EnvironmentLocation}b
    NatGateway3: 
        Type: AWS::EC2::NatGateway
        Properties:
            AllocationId: !GetAtt NatGateway3EIP.AllocationId
            SubnetId: !Ref PublicSubnet3
            Tags:
                - Key: Name
                  Value: !Sub ${EnvironmentName}-${EnvironmentLocation}c
    PublicRouteTable:
        Type: AWS::EC2::RouteTable
        Properties: 
            VpcId: !Ref VPC
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-public
    DefaultPublicRoute: 
        Type: AWS::EC2::Route
        DependsOn: InternetGatewayAttachment
        Properties: 
            RouteTableId: !Ref PublicRouteTable
            DestinationCidrBlock: 0.0.0.0/0
            GatewayId: !Ref InternetGateway
    PublicSubnet1RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
            RouteTableId: !Ref PublicRouteTable
            SubnetId: !Ref PublicSubnet1
    PublicSubnet2RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
            RouteTableId: !Ref PublicRouteTable
            SubnetId: !Ref PublicSubnet2
    PublicSubnet3RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
            RouteTableId: !Ref PublicRouteTable
            SubnetId: !Ref PublicSubnet3
    PrivateRouteTable1:
        Type: AWS::EC2::RouteTable
        Properties: 
            VpcId: !Ref VPC
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-private-${EnvironmentLocation}a
    DefaultPrivateRoute1:
        Type: AWS::EC2::Route
        Properties:
            RouteTableId: !Ref PrivateRouteTable1
            DestinationCidrBlock: 0.0.0.0/0
            NatGatewayId: !Ref NatGateway1
    PrivateSubnet1RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
            RouteTableId: !Ref PrivateRouteTable1
            SubnetId: !Ref PrivateSubnet1
    PrivateRouteTable2:
        Type: AWS::EC2::RouteTable
        Properties: 
            VpcId: !Ref VPC
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-private-${EnvironmentLocation}b
    DefaultPrivateRoute2:
        Type: AWS::EC2::Route
        Properties:
            RouteTableId: !Ref PrivateRouteTable2
            DestinationCidrBlock: 0.0.0.0/0
            NatGatewayId: !Ref NatGateway2
    PrivateSubnet2RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
            RouteTableId: !Ref PrivateRouteTable2
            SubnetId: !Ref PrivateSubnet2
    PrivateRouteTable3:
        Type: AWS::EC2::RouteTable
        Properties: 
            VpcId: !Ref VPC
            Tags: 
                - Key: Name 
                  Value: !Sub ${EnvironmentName}-private-${EnvironmentLocation}c
    DefaultPrivateRoute3:
        Type: AWS::EC2::Route
        Properties:
            RouteTableId: !Ref PrivateRouteTable3
            DestinationCidrBlock: 0.0.0.0/0
            NatGatewayId: !Ref NatGateway3
    PrivateSubnet3RouteTableAssociation:
        Type: AWS::EC2::SubnetRouteTableAssociation
        Properties:
            RouteTableId: !Ref PrivateRouteTable3
            SubnetId: !Ref PrivateSubnet3
    VPNGatewayRouteProp: 
        Type: &quot;AWS::EC2::VPNGatewayRoutePropagation&quot;
        Properties:
            RouteTableIds: [!Ref PublicRouteTable, !Ref PrivateRouteTable1, !Ref PrivateRouteTable2, !Ref PrivateRouteTable3]
            VpnGatewayId: !Ref VPNGateway
        DependsOn: VPNGatewayAttachment
Outputs: 
    VPC: 
        Description: A reference to the created VPC
        Value: !Ref VPC
    PublicSubnets:
        Description: A list of the public subnets
        Value: !Join [ &quot;,&quot;, [ !Ref PublicSubnet1, !Ref PublicSubnet2, !Ref PublicSubnet3 ]]
    PrivateSubnets:
        Description: A list of the private subnets
        Value: !Join [ &quot;,&quot;, [ !Ref PrivateSubnet1, !Ref PrivateSubnet2, !Ref PrivateSubnet3 ]]
    PublicSubnet1:
        Description: A reference to the public subnet in the 1st Availability Zone
        Value: !Ref PublicSubnet1
    PublicSubnet2: 
        Description: A reference to the public subnet in the 2nd Availability Zone
        Value: !Ref PublicSubnet2
    PublicSubnet3: 
        Description: A reference to the public subnet in the 3rd Availability Zone
        Value: !Ref PublicSubnet3
    PrivateSubnet1:
        Description: A reference to the private subnet in the 1st Availability Zone
        Value: !Ref PrivateSubnet1
    PrivateSubnet2: 
        Description: A reference to the private subnet in the 2nd Availability Zone
        Value: !Ref PrivateSubnet2
    PrivateSubnet3: 
        Description: A reference to the private subnet in the 3rd Availability Zone
        Value: !Ref PrivateSubnet3
    VPNGateway:
        Description: A reference to the VPNGateway created in the VPC
        Value: !Ref VPNGateway
</code></pre>
<p>Once your YAML file is setup the way you want, you can log into your AWS account and then:</p>
<ol>
<li>Click Services -&gt; CloudFormation -&gt; Create new stack</li>
<li>Click &quot;Upload a template to Amazon S3&quot; and choose your YAML file</li>
<li>Give the stack a name, ex: prod-us-west-vpc</li>
<li>Change any default parameters if needed, then click &quot;Next&quot; and &quot;Create&quot;</li>
</ol>
<p>Your VPC will be created in the region the GUI is set to, and you can easily delete everything you created by deleting the CloudFormation stack.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Ansible - BadHostKeyException]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>When executing an ansible playbook, you may get the following error:</p>
<pre><code class="language-bash">An exception occurred during task execution. To see the full traceback, use -vvv. The error was: paramiko.BadHostKeyException: Host key for server switch-name does not match!
</code></pre>
<p>This probably happened after you changed the name of your network device, and</p>]]></description><link>https://thenetworkstack.com/ansible-badhostkeyexception/</link><guid isPermaLink="false">64aa27a1fa5680036a0d286c</guid><category><![CDATA[ansible]]></category><category><![CDATA[cisco]]></category><category><![CDATA[ssh]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Sat, 27 Jan 2018 18:58:42 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>When executing an ansible playbook, you may get the following error:</p>
<pre><code class="language-bash">An exception occurred during task execution. To see the full traceback, use -vvv. The error was: paramiko.BadHostKeyException: Host key for server switch-name does not match!
</code></pre>
<p>This probably happened after you changed the name of your network device, and generated new RSA keys.  Or, if you are using DNS device names in ansible, resolve the name of your network device from your ansible server and verify the DNS resolution is correct.  To fix the issue, edit your &quot;known_hosts&quot; file and remove the key associated with the network device throwing the error:</p>
<ol>
<li>Open your known_hosts file</li>
</ol>
<pre><code class="language-bash">vi ~/.ssh/known_hosts
</code></pre>
<ol start="2">
<li>Search for the line with the network device RSA key</li>
</ol>
<pre><code class="language-bash">/network_device_name
</code></pre>
<ol start="3">
<li>Delete the RSA key for that network device (&quot;dd&quot; deletes the entire line)</li>
</ol>
<pre><code class="language-bash">dd
</code></pre>
<ol start="4">
<li>Save the known_hosts file</li>
</ol>
<pre><code class="language-bash">#Press the escape key first
:wq
</code></pre>
<p>If you don&apos;t want ansible to perform this check, edit your <strong>ansible.cfg</strong> file with:</p>
<pre><code>host_key_checking = False
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Pluribus Networks - Whitebox Fabric #NFD16]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>On day two of <a href="http://techfieldday.com/event/nfd16/?ref=thenetworkstack.com" target="_blank">Networking Field Day</a>, Pluribus Networks gave us a rundown on what is possible with their Netvisor OS, whitebox hardware, and a distributed architecture. I was impressed with the flexibility of the solution, but like any design choice, there are some limitations to be aware of.</p>
<p>As</p>]]></description><link>https://thenetworkstack.com/pluribus-networks-whitebox-fabric-nfd16/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e0</guid><category><![CDATA[nfd16]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Fri, 03 Nov 2017 20:21:12 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>On day two of <a href="http://techfieldday.com/event/nfd16/?ref=thenetworkstack.com" target="_blank">Networking Field Day</a>, Pluribus Networks gave us a rundown on what is possible with their Netvisor OS, whitebox hardware, and a distributed architecture. I was impressed with the flexibility of the solution, but like any design choice, there are some limitations to be aware of.</p>
<p>As a relative newcomer to the Pluribus world, I wanted to know what Pluribus was made of. The answer?</p>
<ul>
<li>Whitebox (or Pluribus branded) switch <strong>hardware</strong></li>
<li><strong>Layer 3</strong> connectivity between switches</li>
<li>Pluribus <strong>Netvisor Operating System</strong></li>
</ul>
<br>
<h3 id="hardware">Hardware</h3>
<p>Most switch hardware is now pretty generic, so Pluribus gives you the choice to run Dell, D-Link, Edge-Core or Pluribus hardware, which means the magic is really in the software. I&apos;m not going to spend time going over <a href="http://www.pluribusnetworks.com/products/open-hardware/?ref=thenetworkstack.com" target="_blank">hardware options</a>, because with those choices, you should be able to easily find an option that fits your price/performance needs - that&apos;s the beauty of whitebox.</p>
<h3 id="layer3">Layer 3</h3>
<p>Next on the list, why L3 connectivity? What about my precious L2 network? Well, the Netvisor OS uses VXLAN for L2 connectivity, which gives you some very interesting design flexibility. For example, you can run Cisco or Arista in your core/spine, and just use Pluribus at the edge/leaf nodes (where L2 actually matters). Your core provides L3 connectivity, and your Pluribus edge will route all our L2 traffic as needed over L3 via VXLAN. Why would you do this? How about lowering upgrade costs by leaving your core as-is. Or run two different fabrics side by side. Maybe span your L2 edge across datacenters? Well...let&apos;s not get too crazy...</p>
<p>Pluribus will advertise Netvisor OS as a DCI solution, but like I mentioned before, every design has a trade-off, and generally L2 DCI has a <a href="http://blog.ipspace.net/2011/12/large-scale-l2-dci-true-story.html?ref=thenetworkstack.com" target="_blank">steep price</a> - Pluribus is no different. It is important to ask questions like &quot;What happens to both sides of the fabric if the DCI goes down?&quot;. The good part? The Netvisor fabric will continue to run as-is in split brain mode.  The bad? You will be locked from making any configuration changes on any side until the DCI is restored. Personally, I would run two separate fabrics that are not dependent on the DCI.</p>
<h3 id="netvisoroperatingsystem">Netvisor Operating System</h3>
<p>Now, the most interesting part of the Pluribus solution - Netvisor OS. There are so many different features and components, but I&apos;m only going to focus on two areas that grabbed my attention during the presentation:</p>
<ol>
<li><strong>Management Capabilities</strong></li>
<li><strong>Network Virtualization</strong></li>
</ol>
<br>
<h4 id="managementcapabilities"><em>Management Capabilities</em></h4>
<p>Immediately I noticed that there are no controllers running the Netvisor OS fabric. Each switch is running the Netvisor OS application, with full-mesh connectivity to all other switches in the fabric. You can log into the CLI <em>or</em> Web <em>or</em> API from <em>any</em> switch and manage the entire fabric! Besides fabric wide configuration, you can also revert changes with <strong>fabric wide rollback</strong>. While controller-less has it&apos;s benefits, there are some scaling limitations to be aware of that other &quot;controller-required&quot; solutions do not encounter.  Right now, a Pluribus network is limited to 40 switches in a single fabric. Considering two top-of-rack switches should easily be able to support 1000 VM&apos;s in any modern design (in <a href="https://thenetworkstack.com/the-half-rack-datacenter/" target="_blank">half a rack</a>), this shouldn&apos;t be a concern for many, but it&apos;s good to be aware.</p>
<p>Pluribus has also built out integrations with other management platforms, like VMware and Nutanix. The VMware integration works closely with all the major VMware products - ESXi, VSAN, and NSX. The Netvisor OS switch fabric will automatically build networks and VXLAN tunnels to support new ESXi hosts coming online and on-demand vMotions to ensure full VM mobility across the fabric. VSAN cluster multicast configurations are completely automated on the network side. NSX is particularly interesting, as Netvisor OS doesn&apos;t just provide L3 connectivity for NSX networks, it also provides visibility into the traffic <em><strong>inside</strong></em> the NSX VXLAN tunnels.</p>
<p>On top of management flexibility and third-party integrations, Pluribus has also built out a analytics/telemetry platform that allows deep visibility into all your network traffic. In the future, I&apos;d like to see Pluribus provide a tight integration with Kubernetes for container networking.</p>
<h4 id="networkvirtualization"><em>Network Virtualization</em></h4>
<p>100% Network/Tenant Virtualization. Not everyone <em>needs</em> this feature, but if you do, this is incredibly slick. Pluribus has virtualized the entire network stack for us, just like server hypervisors have done for the systems guys. When you create a new &quot;tenant&quot; in Netvisor OS, the tenant will have their own management portal, full set of VLANs, routing protocols, and policies - all running on the same underlying hardware. Tenant &quot;A&quot; can log into the CLI and make changes completely independent of Tenant &quot;B&quot;. This concept may not be completely new if you are used to working with VDCs on Cisco Nexus 7ks, but if you are used to working on Nexus 9ks (which is what Cisco is pushing for all new datacenter deployments - especially if you are using VXLAN), then this feature will be new to you.</p>
<p><img src="https://thenetworkstack.com/content/images/2017/09/pluribus-virtualization.PNG" alt="pluribus-virtualization" loading="lazy"></p>
<br>
<p>Even if you&apos;re not a multi-tenant datacenter provider, virtualizing your network infrastructure can be used for a number of scenarios:</p>
<ul>
<li>Separate Dev, QA and Prod environments</li>
<li>Separate External, DMZ and Internal networks</li>
<li>PCI network segments</li>
<li>Guest and Contractor networks</li>
<li>Automation testing</li>
</ul>
<p>This is just another way for the network to provide value by reducing network costs for separate environments, and decrease risk by limiting changes to each unique environment.</p>
<p>For new datacenter builds, or even more mild datacenter refreshes, Pluribus has the capability to fit in with a solid set of features and integrations. Giving network operators the choice to bring our own hardware means we&apos;re not limited by the vendor&apos;s hardware pricing or design. And while Pluribus is far from the only company providing a network operating system on whitebox hardware, their network management and virtualization stack are differentiating features that deserve a look.</p>
<br>
<blockquote>
<p><strong>Disclosure:</strong> I attended this presentation as part of Networking Field Day, a <a href="http://techfieldday.com/?ref=thenetworkstack.com">Tech Field Day</a> event. All expenses related to the event were sponsored, in addition to any free swag given out by vendors. All opinions expressed on <a href="https://thenetworkstack.com/">The Network Stack</a> are my own and not those of Tech Field Day, vendors or my employer.</p>
</blockquote>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Troubleshooting Disk Space Usage]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A couple years ago, my coworker wrote a great post on finding disk space issues in Linux and how to resolve them. Helped me out this weekend when a critical server was having issues, so wanted to post it here:</p>
<p><a href="http://www.randomlyexpressed.com/diagnosing-linux-disk-usage/?ref=thenetworkstack.com">http://www.randomlyexpressed.com/diagnosing-linux-disk-usage/</a></p>
<hr>
<br>
<p><strong>For future reference <em>(after reading</em></strong></p>]]></description><link>https://thenetworkstack.com/troubleshooting-disk-space-usage/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e2</guid><category><![CDATA[ubuntu]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Mon, 16 Oct 2017 17:07:40 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A couple years ago, my coworker wrote a great post on finding disk space issues in Linux and how to resolve them. Helped me out this weekend when a critical server was having issues, so wanted to post it here:</p>
<p><a href="http://www.randomlyexpressed.com/diagnosing-linux-disk-usage/?ref=thenetworkstack.com">http://www.randomlyexpressed.com/diagnosing-linux-disk-usage/</a></p>
<hr>
<br>
<p><strong>For future reference <em>(after reading the post above)</em></strong></p>
<p>Show filesystem usage:</p>
<pre><code class="language-bash">~$ df -h
</code></pre>
<p>Show <em>all</em> files/directories consuming space:</p>
<pre><code class="language-bash">~$ du -kx / | sort -nr | more
</code></pre>
<p>Show directories in current location:</p>
<pre><code class="language-bash">~$ du -hc | sort -h
~$ du -hc --max=1 | sort -h #This limits your directory listing to one level
</code></pre>
<p>List files in directory:</p>
<pre><code class="language-bash">~$ ls -larth
</code></pre>
<p>List files in directory sorted by size, ascending:</p>
<pre><code class="language-bash">~$ ls -lSrh
</code></pre>
<p>List and then delete any .log file older than 7 days:</p>
<pre><code class="language-bash">~$ find . -type f -name &quot;*.log&quot; -mtime +7 -print -exec rm -fr {} \;
</code></pre>
<p>Another easy way to reclaim space by removing unused dependencies:</p>
<pre><code class="language-bash">~$ apt-get autoremove
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Ansible - VLAN Provisioning]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><em>Note: There is a <a href="https://thenetworkstack.com/ansible-2-5-new-network-modules/">newer guide</a> for VLAN provisioning with Ansible 2.5</em></p>
<p>Ansible is such a powerfull tool that it can be easy to get lost in all the possibilities. Running your &quot;network infrastructure as code&quot; with full configs auto-generated and checked into git is the dream,</p>]]></description><link>https://thenetworkstack.com/ansible-vlan-provisioning/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28e1</guid><category><![CDATA[ansible]]></category><category><![CDATA[cisco]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Wed, 11 Oct 2017 05:44:05 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><em>Note: There is a <a href="https://thenetworkstack.com/ansible-2-5-new-network-modules/">newer guide</a> for VLAN provisioning with Ansible 2.5</em></p>
<p>Ansible is such a powerfull tool that it can be easy to get lost in all the possibilities. Running your &quot;network infrastructure as code&quot; with full configs auto-generated and checked into git is the dream, but we can <em>start simple</em> with automating time-consuming tasks. This post will focus on getting ansible up and running with a playbook to configure new vlans across your switches.</p>
<blockquote>
<p>If you have not installed Ansible yet, please <a href="https://thenetworkstack.com/ansible-installation/">see my guide for installing Ansible on Ubuntu 16.04</a></p>
</blockquote>
<p>First, we need to build our Ansible <strong>hosts</strong> file which is an inventory list of our network devices. We can categorize and group devices within the hosts file, which makes configuring the right devices easier down the road.</p>
<pre><code class="language-no-highlight">root@ubuntu:~# cd /etc/ansible/
root@ubuntu:/etc/ansible# vi hosts
# This is the default ansible &apos;hosts&apos; file.
#
[networkdevices:children]
switches
routers

[switches]
switch01.thenetworkstack.com
switch02 ansible_host=10.170.200.1
10.170.200.2

[routers]
</code></pre>
<p>I created a parent group called <strong>networkdevices</strong>, and then made two &quot;child&quot; groups called <strong>switches</strong> and <strong>routers</strong>. For the VLAN playbook we are going to create, we only really care about the <strong>switches</strong> group, but I wanted to show how you can easily create a grouping structure. For defining your actual network devices, there are three main options shown above in the <strong>switches</strong> group:</p>
<ul>
<li>The fully-qualified domain name of the device (assuming you have DNS working)</li>
<li>A local device name, and define the device ip address with the &quot;ansible_host&quot; variable</li>
<li>The ip address of the device</li>
</ul>
<p>After you configure your Ansible hosts file with a network device or two, we can start building a <strong>playbook</strong>. A playbook is Ansible&apos;s way of defining a set of tasks. Within a playbook, we will use <strong>network modules</strong> to run different types of commands (for example, <em>show</em> vs <em>config</em>) on our devices. Ansible comes with support for most major network devices, listed here: <a href="http://docs.ansible.com/ansible/latest/list_of_network_modules.html?ref=thenetworkstack.com">http://docs.ansible.com/ansible/latest/list_of_network_modules.html</a></p>
<p>Let&apos;s get started with our playbook. First, give your playbook a name, and make sure it ends in &quot;.yml&quot;. To start your YAML file, the first line should be &quot;---&quot;, and remember <strong>spaces matter</strong>. If you get syntax errors, check your spacing on each line:</p>
<pre><code class="language-no-highlight">root@ubuntu:/etc/ansible# vi network_new-vlan.yml
---
- hosts: switches
  connection: local

  tasks:
    - name: Show VLAN
      ios_command:
        commands: show vlan brief
      register: show_vlan

    - debug: var=show_vlan.stdout_lines
</code></pre>
<p>This simple playbook just runs a command (show vlan brief), registers the output of that command to a variable (show_vlan) and then displays the formatted value of the variable (stdout_lines).</p>
<p>You may notice we don&apos;t have any credentials stored in this playbook - we will provide them when we run the playbook (I&apos;m using <em>cisco</em> as my username):</p>
<pre><code class="language-no-highlight">root@ubuntu:/etc/ansible# ansible-playbook network_new-vlan.yml -u cisco -k
SSH password:

PLAY [switches] *******************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************
ok: [10.170.200.2]

TASK [Show VLAN] *****************************************************************************************************************************************************************
ok: [10.170.200.2]

TASK [debug] **********************************************************************************************************************************************************************
ok: [10.170.200.2] =&gt; {
    &quot;show_vlan.stdout_lines&quot;: [
        [
            &quot;VLAN Name                             Status    Ports&quot;,
            &quot;---- -------------------------------- --------- -------------------------------&quot;,
            &quot;1    default                          active    Gi0/10, Gi0/11, Gi0/12&quot;,
            &quot;10   FW_VLAN                          active    Gi0/3, Gi0/4, Gi0/5, Gi0/6, Gi0/7&quot;,
            &quot;20   Data_VLAN                        active    Gi0/1, Gi0/2&quot;,
            &quot;30   Voice_VLAN                       active    Gi0/1, Gi0/2, Gi0/3, Gi0/4, Gi0/5, Gi0/6, Gi0/7&quot;,
            &quot;1002 fddi-default                     act/unsup &quot;,
            &quot;1003 token-ring-default               act/unsup &quot;,
            &quot;1004 fddinet-default                  act/unsup &quot;,
            &quot;1005 trnet-default                    act/unsup&quot;
        ]
    ]
}

PLAY RECAP ************************************************************************************************************************************************************************
10.170.200.2                : ok=3    changed=0    unreachable=0    failed=0
</code></pre>
<p>Pretty simple! I currently only have a single device in my Ansible hosts file, but with multiple devices you can issue show commands across every switch in your network. You can also modify the playbook above with any &quot;show&quot; command.</p>
<p>We used the &quot;ios_command&quot; network module above, but to actually make changes, we will need to use the &quot;ios_config&quot; network module.</p>
<p>When creating playbooks for common tasks (like creating a vlan), I try to use variables as much as possible so the playbook is easy to reuse. You can see below that I define the <strong>vlan_id</strong> and <strong>vlan_name</strong> variable, which makes them very easy to change when needed - you don&apos;t need to edit anything else in the playbook.</p>
<pre><code class="language-no-highlight">---
- hosts: switches
  connection: local
  vars:
    vlan_id: 998
    vlan_name: Ansible_VLAN

  tasks:
    - name: Configure VLAN ID
      ios_config:
        lines:
          - vlan {{ vlan_id }}

    - name: Configure VLAN Name
      ios_config:
        lines:
          - name {{ vlan_name }}
        parents: vlan {{ vlan_id }}

    - name: Show VLAN
      ios_command:
        commands: show vlan brief
      register: show_vlan

    - debug: var=show_vlan.stdout_lines
</code></pre>
<p>As you can see, we added the VLAN configuration <em>before</em> our &quot;Show VLAN&quot; task. There are two parts to configuring a VLAN - the VLAN ID and the VLAN name. The first task configures the VLAN ID on the switch, then the second task tells Ansible to configure the VLAN name under the VLAN ID we just created. Since the VLAN name is part of a heirarchical configuration in Cisco IOS, we can use the &quot;parents&quot; feature in Ansible to let it know that the name is placed under the VLAN ID configuration.</p>
<p>After the VLAN configuration is completed, our &quot;Show VLAN&quot; task will display the VLAN database with our newly created VLAN.</p>
<pre><code class="language-no-highlight">root@ubuntu:/etc/ansible# ansible-playbook network_new-vlan.yml -u admin -k
SSH password:

PLAY [switches] *******************************************************************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************************************************************
ok: [10.170.200.2]

TASK [Configure VLAN ID] **********************************************************************************************************************************************************
changed: [10.170.200.2]

TASK [Configure VLAN Name] ********************************************************************************************************************************************************
changed: [10.170.200.2]

TASK [Show VLAN] ******************************************************************************************************************************************************************
ok: [10.170.200.2]

TASK [debug] **********************************************************************************************************************************************************************
ok: [10.170.200.2] =&gt; {
    &quot;show_vlan.stdout_lines&quot;: [
        [
            &quot;VLAN Name                             Status    Ports&quot;,
            &quot;---- -------------------------------- --------- -------------------------------&quot;,
            &quot;1    default                          active    Gi0/10, Gi0/11, Gi0/12&quot;,
            &quot;10   FW_VLAN                          active    Gi0/3, Gi0/4, Gi0/5, Gi0/6, Gi0/7&quot;,
            &quot;20   Data_VLAN                        active    Gi0/1, Gi0/2&quot;,
            &quot;30   Voice_VLAN                       active    Gi0/1, Gi0/2, Gi0/3, Gi0/4, Gi0/5, Gi0/6, Gi0/7&quot;,
            &quot;998  Ansible_VLAN                     active    &quot;,
            &quot;1002 fddi-default                     act/unsup &quot;,
            &quot;1003 token-ring-default               act/unsup &quot;,
            &quot;1004 fddinet-default                  act/unsup &quot;,
            &quot;1005 trnet-default                    act/unsup&quot;
        ]
    ]
}

PLAY RECAP ************************************************************************************************************************************************************************
10.170.200.2                : ok=5    changed=2    unreachable=0    failed=0

root@ubuntu:/etc/ansible#
</code></pre>
<p>Success!!</p>
<p>Now when a new VLAN needs to be provisioned, just change the <strong>vlan_id</strong> and <strong>vlan_name</strong> vars, and you can configure a VLAN across your entire network in less than a minute.</p>
<p>You can also find the <strong>hosts</strong> file and <strong>playbook</strong> on my github: <a href="https://github.com/dkuchenski/thenetworkstack-ansible/tree/master/vlan-provisioning?ref=thenetworkstack.com">https://github.com/dkuchenski/thenetworkstack-ansible/tree/master/vlan-provisioning</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Cisco Config Basics - User Port]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>This is my first post in a series I&apos;m calling <strong>Cisco Config Basics</strong>. These posts will serve as a reference for anyone new to Cisco, or those of you just looking to compare your current configs. After the full config, I will explain each config item line-by-line.</p>
<p>In</p>]]></description><link>https://thenetworkstack.com/cisco-config-basics-user-port/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28dd</guid><category><![CDATA[cisco]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Fri, 29 Sep 2017 14:58:38 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>This is my first post in a series I&apos;m calling <strong>Cisco Config Basics</strong>. These posts will serve as a reference for anyone new to Cisco, or those of you just looking to compare your current configs. After the full config, I will explain each config item line-by-line.</p>
<p>In a campus network, the User Port has a lot riding on it - vlan config, security controls, DHCP protection, PoE settings...not to mention new IPv6 policy that is needed <strong>even if you&apos;re not running IPv6</strong> in your network! As promised I will give the full config first, then explain everything:</p>
<p style="padding: .5em 0em; font-weight:bold; font-size:1.3em;">User Port Config (Catalyst 2960X - IOS 15.2.2E6)</p>
<pre><code class="language-no-highlight">interface GigabitEthernet1/0/1
 switchport access vlan 10
 switchport mode access
 switchport voice vlan 20
 switchport port-security maximum 6
 switchport port-security violation  restrict
 switchport port-security aging time 2
 switchport port-security
 load-interval 30
 no snmp trap link-status
 no logging event link-status
 power inline police action log
 no power efficient-ethernet
 storm-control broadcast level pps 1k 500
 storm-control action shutdown
 storm-control action trap
 spanning-tree portfast
 ip dhcp snooping limit rate 100
 ipv6 nd raguard attach-policy RA-BLOCK
 ipv6 dhcp guard attach-policy DHCP-CLIENT
</code></pre>
<p style="padding: .9em 0em .3em 0em;"><i>Whew, that&apos;s a decent amount of config!</i> Let&apos;s take a look:</p>
<p><code>switchport access vlan 10</code><br>
Sets the &apos;untagged&apos; vlan for the port. Most end-user computers/devices are not vlan aware, so this is the vlan the connected device will join.</p>
<p><code>switchport mode access</code><br>
Forces the port into access mode instead of &apos;dynamic desirable&apos; - it will not negotiate to be a trunk port.</p>
<p><code>switchport voice vlan 20</code><br>
Set the &apos;tagged&apos; vlan for VoIP devices. VoIP phones need to know to tag their traffic to this vlan, usually done through CDP, LLDP, or DHCP options.</p>
<p><code>switchport port-security maximum 6</code><br>
Allows a maximum of six devices (mac-addresses) connected to the port. At a minimum, two mac-addresses need to be allowed for their computer and phone. 6 devices allows for a little wiggle room, while still protecting the switch from any mac-address flooding attempts.</p>
<p><code>switchport port-security violation restrict</code><br>
The &apos;restrict&apos; parameter will drop traffic from any mac-addresses past the maximum (6) limit. You can also use the &apos;shutdown&apos; option to shut down the port instead.</p>
<p><code>switchport port-security aging time 2</code><br>
If a device is connected to a port, but inactive, it&apos;s mac-address will be flushed after 2 minutes. Devices that physically disconnect will have their mac-address flushed immediately.</p>
<p><code>switchport port-security</code><br>
The port-security commands above do not take effect until port-security is enabled on the port with this command. By default, port-security will automatically shutdown the port when a new MAC address is detected, which is why we tuned the config above with &apos;violation restrict&apos; and &apos;aging time 2&apos;. You can see the port-security policy on an interface with the command &apos;show port-security interface g1/0/1&apos;.</p>
<p><code>load-interval 30</code><br>
By default, Cisco calculates the load (utilization) of an interface over a 5 minute average. This makes it harder to see bursty traffic, so I prefer to lower the interval to the minimum - 30 seconds.</p>
<p><code>no snmp trap link-status</code><br>
No need to flood your snmp trap server with interface up/down events for user ports. This information isn&apos;t generally helpful since users will be connecting and disconnecting their computers all the time, better to get rid of the noise.</p>
<p><code>no logging event link-status</code><br>
Same as the command above, but for your switch logs and syslog server.</p>
<p><code>power inline police action log</code><br>
Instead of disabling a port for exceeding power allocation, a syslog message is generated, notifying you of a misbehaving device.</p>
<p><code>no power efficient-ethernet</code><br>
Disables Energy Efficient Ethernet (EEE - 802.3az), which is supposed to reduce power consumption during idle usage, but I&apos;ve seen weird behavior from a number of devices that is solved by disabled EEE.</p>
<p><code>storm-control broadcast level pps 1k 500</code><br>
Storm-control is used to detect a flood of broadcast, unknown unicast, or unknown multicast traffic and shutdown the port. The first number represents the &apos;rising threshold&apos; after which traffic is blocked. The second number is the &apos;falling threshold&apos; where traffic will no longer be blocked if it falls back below this value. There are multiple ways to configure this feature (% utilization, bps, pps), but this example uses pps to enforce a 1000 packet-per-second threshold for broadcast traffic, which I have found to be a good general number to start. This number will vary and can be tuned depending on your environment.</p>
<p><code>storm-control action shutdown</code><br>
When a storm is detected, the port is shutdown. The port can recover with the &apos;errdisable recovery&apos; global policy shown below or manually typing &apos;no shutdown&apos; in the interface configuration.</p>
<p><code>storm-control action trap</code><br>
Also sends an SNMP trap when the storm is detected, in addition to the shutdown above.</p>
<p><code>spanning-tree portfast</code><br>
Spanning-tree portfast places the port in the forwarding state immediately, instead of going through all the initial spanning-tree states. Helps the connected computer obtain an IP address and get on the network faster. Only use this if connecting to a non-switch device.</p>
<p><code>ip dhcp snooping limit rate 100</code><br>
Limits the number of DHCP requests to 100 requests per second. This prevents a misconfigured or malicious device from DOS&apos;ing your DHCP server.</p>
<p><code>ipv6 nd raguard attach-policy RA-BLOCK</code><br>
Blocks rogue IPv6 router advertisement (RA) messages. Even if you do not use IPv6 in your network, a rogue device could start advertising itself as a IPv6 router and funnel traffic through itself, since most modern operating systems will prefer IPv6 over IPv4.</p>
<p><code>ipv6 dhcp guard attach-policy DHCP-CLIENT</code><br>
This blocks IPv6 DHCP server replies and advertisements from unauthorized (end-user) ports.</p>
<hr>
<p style="padding: .5em 0em .2em 0em; font-weight:bold; font-size:1.3em;">Global Switch Config</p>
<p>In addition to the user port config, there are global switch settings that are needed as well.</p>
<pre><code class="language-no-highlight">spanning-tree mode rapid-pvst
spanning-tree logging
spanning-tree portfast bpduguard default

errdisable recovery cause udld
errdisable recovery cause bpduguard
errdisable recovery cause link-flap
errdisable recovery cause psecure-violation
errdisable recovery cause dhcp-rate-limit
errdisable recovery cause storm-control

ipv6 nd raguard policy RA-ALLOW
 device-role router
ipv6 nd raguard policy RA-BLOCK
 device-role host #default role
ipv6 snooping logging packet drop
ipv6 snooping logging resolution-veto
ipv6 dhcp guard policy DHCP-CLIENT
 device-role client #default role
ipv6 dhcp guard policy DHCP-TRUST
 trusted-port

ip dhcp snooping vlan 1-4094
no ip dhcp snooping information option
ip dhcp snooping

interface Port-channel1
 ip dhcp snooping trust
</code></pre>
<br>
<p><code>spanning-tree mode rapid-pvst</code><br>
Enables rapid per-vlan spanning-tree, which I would recommend as the default spanning-tree setting for a Cisco network.</p>
<p><code>spanning-tree logging</code><br>
Spanning-tree events are logged in the device logs and syslog.</p>
<p><code>spanning-tree portfast bpduguard default</code><br>
Enables bpduguard on every port that has &apos;spanning-tree portfast&apos; configured. With this, the switch will shutdown any port that recieves bpdus, which protects your network from rogue switches being plugged in and potentially becoming spanning-tree root.</p>
<p><code>errdisable recovery cause udld</code><br>
<code>errdisable recovery cause bpduguard</code><br>
<code>errdisable recovery cause link-flap</code><br>
<code>errdisable recovery cause psecure-violation</code><br>
<code>errdisable recovery cause dhcp-rate-limit</code><br>
<code>errdisable recovery cause storm-control</code><br>
Sets auto-recovery for the policies above (udld, bpduguard, link-flap, psecure-violation, dhcp-rate-limit, storm-control). Default recovery is 300 seconds. If the issue is still present after auto-recovery, the port will shut and wait another 300 seconds.</p>
<p><code>ipv6 nd raguard policy RA-ALLOW</code><br>
<code>device-role router</code><br>
This defines a raguard policy you can attach to a port. This policy would be attached to a port connected to your IPv6 router, as the &apos;device-role router&apos; allows RA&apos;s on the port.</p>
<p><code>ipv6 nd raguard policy RA-BLOCK</code><br>
<code>device-role host (default)</code><br>
This raguard policy is meant to be attached to a user-facing port, and blocks any RA&apos;s received on the port.</p>
<p><code>ipv6 snooping logging packet drop</code><br>
When IPv6 DHCP messages are dropped, a syslog message is generated.</p>
<p><code>ipv6 snooping logging resolution-veto</code><br>
Additional logging in case the switch &apos;vetos&apos; an IPv6 neighbor solicitation.</p>
<p><code>ipv6 dhcp guard policy DHCP-CLIENT</code><br>
<code>device-role client (default)</code><br>
This defines a dhcp guard policy that you can attach to a port. With the role &apos;client&apos; the port will block ingress IPv6 DHCP server reply and advertisement messages.</p>
<p><code>ipv6 dhcp guard policy DHCP-TRUST</code><br>
<code>trusted-port</code><br>
The &apos;trusted-port&apos; setting in this DHCP guard policy allows IPv6 DHCP server reply and advertisement messages. In the configuration example, we are applying the &apos;ipv6 dhcp guard policy DHCP-CLIENT&apos; on each indivitual port, so we don&apos;t need to apply a trusted-port policy to the uplink interface. If you applied the &apos;DHCP-CLIENT&apos; policy to the entire VLAN, then you would need to apply the trusted-port policy on an uplink, but unfortunately Cisco does currently support use of trusted-port policies on etherchannel interfaces.</p>
<p><code>ip dhcp snooping vlan 1-4094</code><br>
You must specify which VLANs IPv4 DHCP snooping is enabled on, and so I enable it for all VLANs. Makes it easy when you add a new VLAN, you don&apos;t have to also modify your DHCP snooping config.</p>
<p><code>no ip dhcp snooping information option</code><br>
Disables the switch from adding option 82 into the DHCP request before forwarding to DHCP server, which I&apos;ve never seen needed (and can potentially break DHCP if you don&apos;t disable it).</p>
<p><code>ip dhcp snooping</code><br>
Enables IPv4 DHCP snooping on the switch. DHCP snooping uses the concept of &apos;trust&apos; to only allow DHCP server reply messages from specified ports. This protects you from someone plugging in a DHCP server and handing out IP addresses to your clients.</p>
<p><code>interface Port-channel1</code><br>
<code>ip dhcp snooping trust</code><br>
This is an example of an IPv4 &apos;trusted&apos; DHCP port. I&apos;m using a port-channel interface, but it can be any type of port, typically an interface that is facing your DHCP server.</p>
<hr>
<p style="padding: .5em 0em; font-weight:bold; font-size:1.3em;">Final Thoughts</p>
<p>After all that, is there anything still left for user facing ports? Of course, <strong>QoS</strong>! I won&apos;t be going over QoS in this post, but it&apos;s an important thing to research and implement correctly, especially if you have VoIP/Video in your environment.</p>
<p>The config above will <em>vary based on your environment</em>, but it&apos;s a solid start to configuring and securing your user edge. Please let me know if you have any suggestions or improvements in the comments below!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Veriflow - The Formal Future #NFD16]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>Formal verification.</strong> Two words unfamiliar to me before Networking Field Day. To provide a brief summary, formal verification uses mathematical proofs to verify a system is working as designed &#x2013; the same process used to create <a href="https://www.quantamagazine.org/formal-verification-creates-hacker-proof-code-20160920/?ref=thenetworkstack.com">hacker-proof code</a>. Veriflow has taken this method and applied it to networking to verify</p>]]></description><link>https://thenetworkstack.com/veriflow-the-formal-future-nfd16/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28df</guid><category><![CDATA[nfd16]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Wed, 20 Sep 2017 04:37:09 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><strong>Formal verification.</strong> Two words unfamiliar to me before Networking Field Day. To provide a brief summary, formal verification uses mathematical proofs to verify a system is working as designed &#x2013; the same process used to create <a href="https://www.quantamagazine.org/formal-verification-creates-hacker-proof-code-20160920/?ref=thenetworkstack.com">hacker-proof code</a>. Veriflow has taken this method and applied it to networking to verify the intended design or operation of the network.</p>
<p>But what does this actually mean to us as network operators? Instead of monitoring isolated metrics like an interfaces&#x2019; utilization, we can monitor the intent of the entire network as a whole, including security policies. As a practical example, you can write policy that says:</p>
<center>
<p><code>The user network should never be able to access tcp port 3306 in the datacenter network.</code></p>
</center>
<center>
<p><em>and</em></p>
</center>
<center>
<p><code>Datacenter network links should always be redundant.</code></p>
</center>
<p>Veriflow will monitor the operational state of your network &#x2013; mac address tables, route tables, access control lists, firewall rules, and alert you if your policy is violated. As more and more network devices are added to your network, this becomes an increasingly powerful tool.</p>
<p><img src="https://thenetworkstack.com/content/images/2017/09/veriflow-slide.PNG" alt="veriflow-slide" loading="lazy"></p>
<br>
<p>Let&#x2019;s get into the nitty gritty, <strong>how does this work</strong>? Veriflow&#x2019;s solution is made up of two components &#x2013; the &#x201C;collector&#x201D; and the &#x201C;verification engine&#x201D;. The collector is a VM that runs in your environment, using SSH credentials to log into your network devices and gather operational state using various &apos;show&apos; commands.</p>
<p>Once the collector has aggregated the data, it forwards all network info to the verification engine, which can be another local VM or SaaS environment run by Veriflow. The nice thing about the SaaS option is that the collector VM never shares your SSH credentials with the verification system. Once the data is in the verification system, it is modeled to predict network-wide behavior and evaluated against any policy rules you have created. Each time the collector retrieves data (user configurable intervals), this is considered a &#x201C;network snapshot&#x201D;, and is kept as long as you have the space to store it. A typical network snapshot is 1-2 MB per device. By keeping these snapshots, you have a documented history of your network, and you can go back to <em>any</em> point in time to see what has changed. Besides security policies, this can help you verify network operation after an operating system upgrade, since Veriflow will inform you of any state change, for example if a routing table is incorrect because of a misapplied route-map.</p>
<p>For Networking Field Day, Veriflow also announced the 2.0 version of its software with two features I wanted to callout:</p>
<ul>
<li>
<p>First, <strong>CloudPredict</strong> enables the collector to use API credentials to connect to your AWS environment and gather routing table info, security group rules, and S3 bucket policies. Since &#x201C;the cloud&#x201D; can sometimes be a wild west run by developers, CloudPredict can allow you to monitor network and security changes even when others have write access to your accounts &#x2013; like when you need to make sure your dev VPC is completely isolated from your PCI VPC.</p>
</li>
<li>
<p>Second, <strong>Preflight</strong> will model your network changes to see potential impact <em>before changes go live</em>. At launch, Preflight only models ACL changes, which is a good start towards more intelligent network change control.</p>
</li>
</ul>
<p>With these new features, and others I haven&#x2019;t mentioned yet (like automatic network diagram generation), Veriflow was one of my favorite presentations at <a href="http://techfieldday.com/event/nfd16/?ref=thenetworkstack.com">NFD16</a>. I think Veriflow is showing us where the future of network monitoring and configuration verification is headed. Monitoring the network intent is much more elegant that writing individual alert rules for interface utilization, cpu and memory thresholds, and link up/down events. Testing network policy before applying to your live network &#x2013; that&#x2019;s a dream most of us can&#x2019;t afford with completely redundant network hardware.</p>
<p>Veriflow is doing a lot right, and while listening to their presentation I couldn&apos;t help but think about how their platfrom could be expanded into additional areas. I&apos;ll be watching to see if any of the following will be rolled into future releases:</p>
<ol>
<li>Expand Preflight checks to include more components, with API access so we can build Preflight config verification into network automation workflows.</li>
<li>Network utilization analysis. If a link is becoming saturated, use historical data of other existing links to know where traffic should be moved to. If a network device fails, will traffic flow overload the remaining links?</li>
<li>Gather netflow data from the network to compare operational state to actual network flows - also use with Preflight checks to show what traffic flows would be affected.</li>
</ol>
<p>Formal verification and monitoring the &quot;intent&quot; of the network are exciting advances, and I believe will have a real impact for the network operator.</p>
<br>
<p><a href="https://www.veriflow.net/press/veriflow-delivers-industrys-first-verification-solution-hybrid-cloud-networks/?ref=thenetworkstack.com">Veriflow 2.0 Press Release</a></p>
<blockquote>
<p><strong>Disclosure:</strong> I attended this presentation as part of Networking Field Day, a <a href="http://techfieldday.com/?ref=thenetworkstack.com">Tech Field Day</a> event. All expenses related to the event were sponsored, in addition to any free swag given out by vendors. All opinions expressed on <a href="https://thenetworkstack.com/">The Network Stack</a> are my own and not those of Tech Field Day, vendors or my employer.</p>
</blockquote>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[SSH with Duo MFA and Active Directory]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Duo has thorough <a href="https://duo.com/docs/duounix?ref=thenetworkstack.com">documentation</a> for adding MFA to your SSH sessions, but there are a couple additional steps needed to also integrate with Active Directory. This post will go through the installation for both Duo and Active Directory for Ubuntu 16.04. For other Linux distros, the Duo documentation linked</p>]]></description><link>https://thenetworkstack.com/ssh-with-duo-mfa-and-active-directory/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28de</guid><category><![CDATA[duo]]></category><category><![CDATA[mfa]]></category><category><![CDATA[ubuntu]]></category><category><![CDATA[active-directory]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Wed, 30 Aug 2017 23:03:22 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Duo has thorough <a href="https://duo.com/docs/duounix?ref=thenetworkstack.com">documentation</a> for adding MFA to your SSH sessions, but there are a couple additional steps needed to also integrate with Active Directory. This post will go through the installation for both Duo and Active Directory for Ubuntu 16.04. For other Linux distros, the Duo documentation linked above has you covered.<br>
<br></p>
<h4 id="systemcomponents"><strong>System components:</strong></h4>
<ul>
<li>Ubuntu 16.04 server</li>
<li>Duo MFA account</li>
<li>Duo Unix package</li>
<li>Centify Express for Active Directory integration<br>
<br></li>
</ul>
<h4 id="duoinstallation"><strong>Duo Installation:</strong></h4>
<p>Install OpenSSL development headers and libraries:</p>
<pre><code class="language-bash">apt-get install libssl-dev libpam-dev -y
</code></pre>
<p>Add Duo repository and install duo-unix package:</p>
<pre><code class="language-bash">echo &apos;deb http://pkg.duosecurity.com/Ubuntu xenial main&apos; | tee /etc/apt/sources.list.d/duosecurity.list
curl -s https://duo.com/APT-GPG-KEY-DUO | apt-key add -
apt-get update
apt-get install duo-unix
</code></pre>
<p>Edit <strong>/etc/duo/pam_duo.conf</strong> with your integration key, secret key, and API host. You can find these values in the <a href="https://admin.duosecurity.com/?ref=thenetworkstack.com">Duo Administration page</a> for your &quot;UNIX Application&quot;.</p>
<pre><code>[duo]
; Duo integration key
ikey = XXXXXXXXXXXXXXXXXXXXXXX
; Duo secret key
skey = XXXXXXXXXXXXXXXXXXXXXXX
; Duo API host
host = XXXXXXXXXXXXXXXXXXXXXXX
; Send command for Duo Push authentication
;pushinfo = yes
</code></pre>
<br>
<h4 id="centrifyinstallation"><strong>Centrify Installation:</strong></h4>
<p>First, edit <strong>/etc/ssh/sshd_config</strong> so that ChallengeResponseAuthentication is set to &quot;yes&quot;</p>
<pre><code class="language-bash"># Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication yes
</code></pre>
<p>Download, unzip, and install Centrify Express:</p>
<pre><code class="language-bash">wget https://downloads.centrify.com/products/centrify-suite/2017-update-1/centrify-suite-2017.1-deb7-x86_64.tgz
tar -xvzf centrify-suite-2017.1-deb7-x86_64.tgz
./install-express.sh
</code></pre>
<p>Go through the installation script to connect to your Active Directory environment:</p>
<pre><code class="language-bash">You can type Q at any prompt to quit the installation and exit
the script without making any changes to your environment.

How do you want to proceed? (E|S|X|C|Q) [X]: X
Do you want to continue to install in Express mode? (C|Y|Q|N) [Y]:Y

Do you want to run adcheck to verify your AD environment? (Q|Y|N) [Y]:Y

Please enter the Active Directory domain to check [company.com]: your-domain.com
Join an Active Directory domain? (Q|Y|N) [Y]:Y
    Enter the Active Directory domain to join [your-domain.com]:
    Enter the Active Directory authorized user [administrator]: your-admin
    Enter the password for the Active Directory user:
    Enter the computer name [server-name]:
    Enter the container DN [Computers]:
    Enter the name of the domain controller [auto detect]:
Reboot the computer after installation? (Q|Y|N) [Y]: Y
</code></pre>
<p>After the server restarts, you should be able to login with your Active Directory credentials via SSH, but you are not prompted for Duo MFA. To support this, we need to edit <strong>/etc/pam.d/common-auth</strong> as follows:</p>
<pre><code class="language-bash"># lines inserted by Centrify Direct Control { CentrifyDC 5.4.1-455 }
#auth   sufficient      pam_centrifydc.so
#auth   requisite       pam_centrifydc.so deny
auth    requisite       pam_centrifydc.so

# here are the per-package modules (the &quot;Primary&quot; block)
#auth   [success=1 default=ignore]      pam_unix.so nullok_secure
auth    requisite       pam_unix.so nullok_secure
auth  [success=1 default=ignore] /lib64/security/pam_duo.so
</code></pre>
<p>In both sections, I commented out the existing config and added the necessary lines so that pam_duo is used after a successful pam_centrifydc authentication.</p>
<p>Next, we need to edit <strong>/etc/pam.d/sshd</strong> and comment out &quot;@include common-auth&quot; so we can add the Centrify and Duo PAM modules (but we don&apos;t need pam_unix):</p>
<pre><code class="language-bash"># Standard Un*x authentication.
#@include common-auth
auth    requisite       pam_centrifydc.so
auth    [success=1 default=ignore]      /lib64/security/pam_duo.so
auth    requisite       pam_deny.so
auth    required        pam_permit.so
</code></pre>
<p>You should be able to SSH to the server with your Active Directory credentials, and then be prompted for Duo MFA (assuming you have a Duo account that matches your AD username)<br>
<br></p>
<h4 id="activedirectorygrouprestriction"><strong>Active Directory Group Restriction:</strong></h4>
<p>You may also want to restrict SSH access to users in a certain Active Directory group. This can be done with two lines in <strong>/etc/ssh/sshd_config</strong> at the end of the config, after &quot;UsePAM yes&quot;:</p>
<pre><code class="language-bash">UsePAM yes
#########
UseDNS no
AllowGroups root your-group-name
</code></pre>
<p>Be sure to add the &apos;root&apos; group so that you can still manage your server with the root account if needed. Restart SSH and your group restriction will be in effect:</p>
<pre><code class="language-bash">service ssh restart
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[The Half Rack Datacenter]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>A couple years ago, Ivan Pepelnjak wrote an interesting blog showing how <a href="http://blog.ipspace.net/2014/10/all-you-need-are-two-top-of-rack.html?ref=thenetworkstack.com">all you need are two top-of-rack switches</a>. Iwan Rahabok followed up on the systems side, with the perspective that <a href="http://virtual-red-dot.info/1000-vm-per-rack-is-the-new-minimum/?ref=thenetworkstack.com">1000 VM per rack is the new minimum</a>.</p>
<p>Now in mid 2017, I&apos;d like to show you</p>]]></description><link>https://thenetworkstack.com/the-half-rack-datacenter/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28dc</guid><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Tue, 22 Aug 2017 15:03:49 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>A couple years ago, Ivan Pepelnjak wrote an interesting blog showing how <a href="http://blog.ipspace.net/2014/10/all-you-need-are-two-top-of-rack.html?ref=thenetworkstack.com">all you need are two top-of-rack switches</a>. Iwan Rahabok followed up on the systems side, with the perspective that <a href="http://virtual-red-dot.info/1000-vm-per-rack-is-the-new-minimum/?ref=thenetworkstack.com">1000 VM per rack is the new minimum</a>.</p>
<p>Now in mid 2017, I&apos;d like to show you how we can fit <strong>2M network routes</strong>, <strong>1PB of storage</strong>, and over <strong>1000 VM&apos;s</strong> in a <strong>half rack</strong>. Don&apos;t worry, I included redundancy as well.</p>
<p><em>Disclaimer: My examples use specific vendor equipment to show how this is possible, but I&apos;m sure you can find different devices to acheive the same goal. I am not employed by any of these vendors, and only picked this equipment because it fits the design goal well.</em></p>
<br>
<h4 id="infrastructure"><strong>Infrastructure:</strong></h4>
<p>(2) Arista 7280CR2K-30<br>
(10) Netapp HCI 2U Servers - 13x Large Compute Nodes &amp; 25x Large Storage Nodes</p>
<p>My network choice is fairly straight-forward. Dual-purpose switches with high-capacity ports that support 10/25/40/50/100 GbE, and also function as edge peering routers that handle 2M routes each.</p>
<p>For compute/storage, I chose to go hyper-converged, as I believe the era of big storage controllers is over. Distributed, fast storage is here to stay, and using something like Netapp HCI provides a controller-less architecture that allows you to add capacity and performance without worrying about your controller throughput. To be fair, I&apos;ve been wary of hyper-converged products, but Netapp HCI retains the benefit of separate compute/storage upgrades like a traditional compute/storage stack.</p>
<center>
<p><img src="https://thenetworkstack.com/content/images/2017/08/half-rack-datacenter.png" alt="half-rack-datacenter" loading="lazy"></p>
</center>
<hr>
<br>
<h4 id="computesizing"><strong>Compute Sizing:</strong></h4>
<p>I currently run enterprise, dev, qa and prod workloads in 100% virtualized environments. I have VM&apos;s that range from 1 vCPU and 512 Mb RAM to 16 vCPU and 64 Gb RAM. I took my total provisioned vCPU/RAM and divided by total VM&apos;s to get my average use, which is 2 vCPU and 4Gb RAM per VM.</p>
<p>1000 VM = <em>2000 vCPU</em> and <em>4 Tb RAM</em></p>
<p>I do not overcommit RAM, but I overcommit 5:1/vCPU:pCPU with good results. This may vary in your environment.</p>
<p>2000 vCPU &#xF7; 5 = <em>400 pCPU</em></p>
<p>Each Netapp HCI large compute node contains 36 pCPU.</p>
<p>400 pCPU &#xF7; 36 = <em>11.1 Netapp large compute nodes</em>, lets round up to 12. N+1 means we need <em>13 large nodes</em>. This will also provide almost 10 Tb of RAM, which is more than enough. <em>Note: If you can push 10:1 overcommit on your compute, you can run 2000 VM&apos;s per half rack!</em></p>
<h4 id="storagesizing"><strong>Storage Sizing:</strong></h4>
<p>Netapp claims 44 Tb of storage capacity with 10x space efficiency (dedup/compression/compaction) per large storage node. This may seem like a stretch, but it really depends on your workloads. My datastores see anywhere from 1.5x to 38x efficiency. My average is 23x, so 10x is actually a very reasonable number for me.</p>
<p>1 Pb &#xF7; 44 Tb = <em>23.2 Large storage nodes</em>, round up to 24. N+1 means we need <em>25 large nodes</em>.</p>
<hr>
<p><em>Compute and Storage Totals:</em></p>
<p>13 Compute + 25 Storage = <em>38 Total Nodes</em>. Each 2U Netapp HCI server holds 4 nodes, so divide 38 by 4 = <em>9.5 2U servers</em>. 10 servers will give us 2 free node slots for future use, and we use a total of 20U.</p>
<hr>
<h4 id="networkroutingswitching"><strong>Network Routing/Switching:</strong></h4>
<p>Each Netapp HCI node has 2x or 4x 10/25Gb ports (depending if its a compute or storage node). For our configuration, we will just use 2x 25Gb ports per node, for a total of 76 25Gb ports for the servers. We also need 2x ports for internet peering, and another 2x ports for WAN connectivity for a total of 80 ports. Each Arista 7280CR2K-30 gives us 120 10/25Gb ports, so we have plenty of capacity. The 7280CR2K-30 also handles 2M routes, so we can take full internet BGP feeds with no problem. Just separate your internal/external route tables appropriately.</p>
<h4 id="security"><strong>Security:</strong></h4>
<p>To keep everything to a half rack, we can use VMware NSX with distributed Palo Alto firewalls. If you prefer a physical firewall, the Arista switches have plenty of room, you will just go over our half rack goal  :)</p>
<br>
<br>
<h4 id="andthereyouhaveit2mnetworkroutes1pbofstorageandover1000vmsinahalfrack">And there you have it! <strong>2M network routes</strong>, <strong>1PB of storage</strong>, and over <strong>1000 VM&apos;s</strong> in a <strong>half rack</strong>.</h4>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Active Directory Powershell]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Using this page to keep track of all the useful powershell &quot;mini-scripts&quot; I&apos;ve used:</p>
<p><strong>Copy users from one security group to another security group</strong></p>
<pre><code>Add-ADGroupMember -Identity destination-group-name -Members (Get-ADGroupMember -Identity source-group-name -Recursive)
</code></pre>
<p><strong>Add <em>enabled</em> users from an OU to a security group</strong></p>
<pre><code>Get-ADUser -SearchBase &apos;OU=</code></pre>]]></description><link>https://thenetworkstack.com/active-directory-powershell/</link><guid isPermaLink="false">64aa27a1fa5680036a0d28d8</guid><category><![CDATA[powershell]]></category><category><![CDATA[active-directory]]></category><category><![CDATA[windows]]></category><dc:creator><![CDATA[Daniel Kuchenski]]></dc:creator><pubDate>Fri, 04 Aug 2017 19:28:01 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Using this page to keep track of all the useful powershell &quot;mini-scripts&quot; I&apos;ve used:</p>
<p><strong>Copy users from one security group to another security group</strong></p>
<pre><code>Add-ADGroupMember -Identity destination-group-name -Members (Get-ADGroupMember -Identity source-group-name -Recursive)
</code></pre>
<p><strong>Add <em>enabled</em> users from an OU to a security group</strong></p>
<pre><code>Get-ADUser -SearchBase &apos;OU=Your-OU,DC=corp,DC=company,DC=com&apos; -Filter {Enabled -eq $true} | ForEach-Object {Add-ADGroupMember -Identity &apos;your-group-name&apos; -Members $_ }
</code></pre>
<p><strong>Add users from a CSV file to a security group (username column is called &quot;name&quot;)</strong></p>
<pre><code>import-csv c:\users.csv | Foreach-Object {add-adgroupmember -Identity your-group-name -Members $_.name}
</code></pre>
<p><strong>Update user objects with organization attributes from a CSV file</strong></p>
<pre><code>import-csv c:\users.csv | Foreach-Object {Set-ADUser -Identity $_.name -Department $_.department -Title $_.title -Manager $_.manager}
</code></pre>
<p><strong>Create security-groups from a CSV file (group-name column is called &quot;name&quot;)</strong></p>
<pre><code>import-csv c:\groups.csv | Foreach-Object {new-adgroup -name $_.name -GroupCategory security -GroupScope global -Path &quot;ou=Your-OU,dc=corp,dc=company,dc=com&quot;}
</code></pre>
<p><strong>Export list of all <em>enabled</em> users in an OU</strong></p>
<pre><code>Get-ADUser -SearchBase &apos;OU=Your-OU,DC=corp,DC=company,DC=com&apos; -Filter {Enabled -eq $true} -Property * | Select -Property Name,SamAccountName,UserPrincipalName,mail,Title,Manager,Department | export-csv &apos;c:\users.csv&apos; -notype
</code></pre>
<p><strong>Export list of all <em>enabled</em> users in an security group</strong></p>
<pre><code>Get-ADGroupMember -Identity your-group-name | ? ObjectClass -eq &quot;User&quot; | Get-ADUser | ? Enabled | Select Name | out-file C:\group_membership.txt
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>