tag:blogger.com,1999:blog-32662630341240054852024-03-27T06:37:46.388+00:00Fragmentation Neededchris margethttp://www.blogger.com/profile/09716555871346949419noreply@blogger.comBlogger136125tag:blogger.com,1999:blog-3266263034124005485.post-87782270641478822442022-03-30T21:52:00.000+01:002022-03-30T21:52:12.782+01:00Set git behavior based on the repository path<p>I maintain a handful of git accounts at GitHub.com and on private git servers, and have repeated committed to a project using the wrong personality.</p><p>My early attempts to avoid this mistake involved scripts to set per-project git parameters, but I've found a more streamlined option.</p><p>The approach revolves around the file hierarchy in my home directory: Rather than dumping everything in a single <span style="font-family: courier;">~/projects</span> directory, they're now in <span style="font-family: courier;">~/projects/personal</span>, <span style="font-family: courier;">~/projects/work</span>, etc...</p><p>Whenever cloning a new project, or starting a new one, as long as I put it in the appropriate directory, git will chose the behaviors and identity appropriate for that project.</p><p>Here's how it works, with 'personal' and 'work' accounts at GitHub.com</p><h1 style="text-align: left;"><span>1. Generate an SSH key for each account</span></h1><div>Not strictly required, I guess, but I like the privacy-preserving angle of using different keys everywhere, so I do this as a matter of habit.</div>
<pre style="background-color: #f0f0f0; background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed rgb(204, 204, 204); color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> ssh-keygen -t ed25519 -P '' -f ~/.ssh/work.github.com
ssh-keygen -t ed25519 -P '' -f ~/.ssh/personal.github.com
</code></pre><h1 style="text-align: left;"><span style="font-size: large;">
2. Add each public key to its respective GitHub account.</span></h1><div>Use <span style="font-family: courier;">~/.ssh/work.github.com.pub</span> and <span style="font-family: courier;">~/.ssh/personal.github.com.pub</span> (note the .pub suffix).</div><div><br /></div><div>Instructions <a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account">here</a>.</div><h1 style="text-align: left;"><span style="font-size: large;">3. Create the project directories and .gitconfig files</span></h1>
<pre style="background-color: #f0f0f0; background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed rgb(204, 204, 204); color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mkdir -p ~/projects/{personal,work}
touch ~/projects/{personal,work}/.gitconfig </code></pre><h1 style="text-align: left;"><span style="font-size: large;">4. Set up a .gitconfig file in each directory</span></h1><div>The git behaviors which should be differentiated by the parent folder belong in that folder's <span style="font-family: courier;">.gitconfig</span> file. My <span style="font-family: courier;">~/projects/work/.gitconfig</span> for example:</div><div><pre style="background-color: #f0f0f0; background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed rgb(204, 204, 204); color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> [user]
email = chris@work.domain
[core]
sshCommand = "ssh -i ~/.ssh/work.github.com"
</code></pre></div><div>Because I only use a single git service/server with each directory/domain (personal/work), I opted to select my private key using the <span style="font-family: courier;">-i <filename></span> option to the <span style="font-family: courier;">ssh</span> command. In a more complicated scenario, it might make sense to use <span style="font-family: courier;">-F <filename></span> to select an alternate <span style="font-family: courier;">ssh</span> configuration file and specify keys per host there.</div><div><br /></div><h1 style="text-align: left;"><span style="font-size: large;">5. Conditionally include project gitconfig from main gitconfig</span></h1><div>My main .gitconfig looks something like this:</div><div><br /></div><pre style="background-color: #f0f0f0; background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: #f0f0f0; border: 1px dashed rgb(204, 204, 204); color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> [init]
defaultBranch = main
[user]
name = Chris Marget
[core]
excludesFile = ~/.gitignore
[includeIf "gitdir:~/projects/work/"]
path = ~/projects/work/.gitconfig
[includeIf "gitdir:~/projects/personal/"]
path = ~/projects/personal/.gitconfig
</code></pre><h1 style="text-align: left;">That's it!</h1><div>Any work done in <span style="font-family: courier;">~/projects/personal/somerepo</span> will automatically use the git behavior specified by <span style="font-family: courier;">~/projects/personal/.gitconfig</span>.</div><div><br /></div><div>I wasn't confident that the <span style="font-family: courier;">gitdir</span> condition would match when cloning an existing repo (the directory doesn't exist yet!) but it works the way I'd hoped. <span style="font-family: courier;">clone/commit/push</span> operations all now use the intended directory-specific configuration options.</div>chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-13513397105685329522022-03-11T21:57:00.005+00:002022-03-13T16:41:54.383+00:00Dell 2161DS-2 serial port pinout<p>I picked up a Dell (Avocent) 2161DS-2 (same as 4161DS?) KVM recently, and needed to use the serial port to upgrade the software.</p><p>Naturally, the serial port pinout is non-standard and requires a proprietary cable which comes with the KVM. Dell part numbers 80DH7 and 3JY78 might be involved. I don't have, and have never seen these cables.</p><p>I was able to to find the RX, TX and Ground pins and interact with the system using 9600, 8, N, 1.</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEggPJpGfdFzlaVtO-8v4JRWSoK_w-4cuqw4JF6Old2_dG0anklihnTBSyIK29k_uZ3Bin5Diw-uIa2SgXNjeMuN8iM_Wv1SaDJYXHm5u9D-jIHtieK4-SSTsEClfnmj4uHBAxQfEcroxxvqexsbMwF17iJRX39Y7YLHSVv9KbRqxUqM1uU-kjFMNo3Z=s854" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="364" data-original-width="854" height="170" src="https://blogger.googleusercontent.com/img/a/AVvXsEggPJpGfdFzlaVtO-8v4JRWSoK_w-4cuqw4JF6Old2_dG0anklihnTBSyIK29k_uZ3Bin5Diw-uIa2SgXNjeMuN8iM_Wv1SaDJYXHm5u9D-jIHtieK4-SSTsEClfnmj4uHBAxQfEcroxxvqexsbMwF17iJRX39Y7YLHSVv9KbRqxUqM1uU-kjFMNo3Z=w400-h170" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Pinout in red text</td></tr></tbody></table><br /><p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjnJVQ45Y239upxwWVJcr_2wSLgiTaIb48ZGJWGK4pQCgBA0Y6fyXAsMUcLf884x2KBonTE_F-T9AhgFo7lohwGgV-YtKs2jokGW8_OAK_WSCuWWCYmNoe2sKNyhTh-N2HfkFWCQ8pRpZ2K0fLWSTY1ildoNxScz4XbCEVJzdeWoFZukvqWTCPSqpL_=s4032" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/a/AVvXsEjnJVQ45Y239upxwWVJcr_2wSLgiTaIb48ZGJWGK4pQCgBA0Y6fyXAsMUcLf884x2KBonTE_F-T9AhgFo7lohwGgV-YtKs2jokGW8_OAK_WSCuWWCYmNoe2sKNyhTh-N2HfkFWCQ8pRpZ2K0fLWSTY1ildoNxScz4XbCEVJzdeWoFZukvqWTCPSqpL_=w400-h300" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Is the color coding inside these adaptors standardized? If so this may help.</td></tr></tbody></table><br /></p><p>The system prints some unsolicited messages ("welcome" or somesuch) a little while after power-up.</p><p>Notes from upgrading the firmware from MacOS 12:</p><p><br /></p>
<pre style="background-color: #f0f0f0; background-image: URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif); background: rgb(240, 240, 240); border: 1px dashed rgb(204, 204, 204); color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; overflow-wrap: normal; word-wrap: normal;"> # Grab the firmware
URL="https://dl.dell.com/RACK SOLUTIONS/DELL_MULTI-DEVICE_A04_R301142.exe"
wget -P /tmp "$URL"
# Start MacOS tftp service
sudo launchctl load -w /System/Library/LaunchDaemons/tftp.plist
# Extract the firmware (it's a self-extracting exe, but we can open it with unzip)
sudo unzip -d /private/tftpboot "/tmp/$(basename "$URL")" Omega_DELL_1.3.51.0.fl
# Now, using the menu on the KVM serial port, point it toward the MacOS TFTP service
# to retrieve the Omega_DELL_1.3.51.0.fl file
</code></pre><br />chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com1tag:blogger.com,1999:blog-3266263034124005485.post-35015120166789653142021-03-02T03:14:00.000+00:002021-03-02T03:14:01.635+00:00VPC peering with terraform<p>I wrote up an example of using terraform modules and provider aliases to turn up interconnected cloud resources (vpcs / vpc peering / peering acceptance / routes) across multiple cloud regions.</p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-nVN5nRCtkP4/YD2rox41vgI/AAAAAAAAA7Q/4IEJCMSOFfkkkUlKjU12gpFhPGYbpj2vwCLcBGAsYHQ/s511/Untitled%2BDiagram-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="451" data-original-width="511" src="https://1.bp.blogspot.com/-nVN5nRCtkP4/YD2rox41vgI/AAAAAAAAA7Q/4IEJCMSOFfkkkUlKjU12gpFhPGYbpj2vwCLcBGAsYHQ/s16000/Untitled%2BDiagram-2.png" title="The topology" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div>Check it out <a href="https://github.com/chrismarget/multi-region-terraform-example">at GitHub</a>.<p></p>chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-79906652246481147852019-12-21T22:21:00.000+00:002019-12-31T18:53:25.933+00:00How do RFC3161 timestamps work?<a href="https://upload.wikimedia.org/wikipedia/commons/6/6b/Truth_or_Consequences_NM_Postmark.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="575" data-original-width="591" height="194" src="https://upload.wikimedia.org/wikipedia/commons/6/6b/Truth_or_Consequences_NM_Postmark.jpg" width="200" /></a>RFC3161 exists to demonstrate that a particular piece of information existed at a certain time, by relying on a timestamp attestation from a trusted 3rd party. It's the cryptographic analog of relying on the date found on a postmark or a notary public's stamp.<br />
<br />
How does it work? Let's timestamp some data and rip things apart as we go.<br />
<br />
First, we'll create a document and have a brief look at it. The document will be one million bytes of random data:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $ <b>dd if=/dev/urandom of=data bs=1000000 count=1</b>
1+0 records in
1+0 records out
1000000 bytes transferred in 0.039391 secs (25386637 bytes/sec)
$ <b>ls -l data</b>
-rw-r--r-- 1 chris staff 1000000 Dec 21 14:10 data
$ <b>shasum data</b>
3de9de784b327c5ecec656bfbdcfc726d0f62137 data
$
</code></pre>
<br />
Next, we'll create a timestamp request based on that data. The <b><span style="font-family: "courier new" , "courier" , monospace;">-cert</span></b> option asks the timestamp authority (TSA) to include their identity (certificate chain) in their reply and <span style="font-family: "courier new" , "courier" , monospace;"><b>-no_nonce</b></span> omits anti-replay protection from the request. Without specifying that option we'd include a large random number in the request.<br />
<br />
<pre style="background-color: #f0f0f0; background-position: initial initial; background-repeat: initial initial; border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $ <b>openssl ts -query -cert -no_nonce < data | hexdump -C</b>
Using configuration from /opt/local/etc/openssl/openssl.cnf
00000000 30 29 02 01 01 30 21 30 09 06 <span style="color: #0b5394;"><b>05 2b 0e 03 02 1a</b></span> |0)...0!0...+....|
00000010 05 00 04 14 <span style="color: #38761d;"><b>3d e9 de 78 4b 32 7c 5e ce c6 56 bf</b></span> |....=..xK2|^..V.|
00000020 <span style="color: #38761d; font-weight: bold;">bd cf c7 26 d0 f6 21 37</span><b> </b><span style="color: #741b47;"><b>01 01 ff</b></span> |...&..!7...|
0000002b
$
</code></pre>
<br />
The timestamp request is only 43 bytes, so we're definitely not sending the <i>actual document</i> (one million bytes) to the TSA. So what's in the request?<br />
<br />
Perusing the data, a couple of things (the two mandatory items, in fact) stand out. First, <span style="color: #38761d;">the SHA1 hash</span> of the data that we captured earlier appears here in the timestamp request. Second <span style="color: #0b5394;">the OID specifying SHA1</span> is included here. The OID (<span style="font-family: "courier new" , "courier" , monospace;">1.3.14.3.2.26</span>) is a little less recognizable because of the insane way OIDs are encoded in ASN.1 (<a href="https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-X.690-200811-S!!PDF-E&type=items">section 8.19</a>), but there it is. The only other information included in the request is result of the <span style="font-family: "courier new" , "courier" , monospace;"><b>-cert</b></span> flag, which is a boolean (true) in the <span style="color: #741b47;">last 3 bytes</span>. I found that the TSA refused to respond if I failed to request the signer include its certificate chain.<br />
<br />
Okay, lets re-generate that request and send it to a real TSA:<br />
<br />
<pre style="background-color: #f0f0f0; background-position: initial initial; background-repeat: initial initial; border: 1px dashed rgb(204, 204, 204); font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="word-wrap: normal;"> $ <b style="color: black;">openssl ts -query -cert -no_nonce < data | curl --data-binary @- http://timestamp.entrust.net/TSS/RFC3161sha2TS | hexdump -C</b>
Using configuration from /opt/local/etc/openssl/openssl.cnf
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3773 100 3730 100 43 24064 277 --:--:-- --:--:-- --:--:-- 24500
00000000 30 82 0e 8e 30 03 02 01 00 30 82 0e 85 06 09 <span style="color: purple;"><b>2a</b></span> |0...0....0.....*|
00000010 <span style="color: purple;"><b>86 48 86 f7 0d 01 07 02</b></span> a0 82 0e 76 30 82 0e 72 |.H.........v0..r|
00000020 02 01 03 31 0b 30 09 06 </code><code style="word-wrap: normal;"><span style="color: #0b5394;"><b>05 2b 0e 03 02 1a</b></span></code><code style="color: black; word-wrap: normal;"> 05 00 |...1.0...+......|
00000030 30 81 e2 06 0b 2a 86 48 86 f7 0d 01 09 10 01 04 |0....*.H........|
00000040 a0 81 d2 04 81 cf 30 81 cc 02 01 01 06 09 </code><code style="word-wrap: normal;"><span style="color: #e69138;"><b>60 86</b></span></code><code style="color: black; word-wrap: normal;"> |......0.......`.|
00000050 </code><code style="word-wrap: normal;"><span style="color: #e69138;"><b>48 86 fa 6c 0a 03 05</b></span></code><code style="color: black; word-wrap: normal;"> 30 21 30 09 06 05 2b 0e 03 |H..l...0!0...+..|
00000060 02 1a 05 00 04 14 </code><code style="word-wrap: normal;"><span style="color: #38761d;"><b>3d e9 de 78 4b 32 7c 5e ce c6</b></span></code><code style="color: black; word-wrap: normal;"> |......=..xK2|^..|
00000070 </code><code style="word-wrap: normal;"><span style="color: #38761d;"><b>56 bf bd cf c7 26 d0 f6 21 37</b></span></code><code style="color: black; word-wrap: normal;"> 02 06 5d eb 11 2b |V....&..!7..]..+|
00000080 86 c9 18 13 </code><code style="word-wrap: normal;"><span style="color: #cc0000;"><b>32 30 31 39 31 32 32 31 32 30 30 38</b></span></code><code style="color: black; word-wrap: normal;"> |....</code><code style="word-wrap: normal;"><span style="color: #cc0000;"><b>201912212008</b></span></code><code style="color: black; word-wrap: normal;">|
00000090 </code><code style="word-wrap: normal;"><span style="color: #cc0000;"><b>30 36 2e 30 30 34 5a 30</b></span></code><code style="color: black; word-wrap: normal;"> 04 80 02 </code><code style="word-wrap: normal;"><span style="color: #7f6000;"><b>01 f4</b></span></code><code style="color: black; word-wrap: normal;"> a0 76 a4 |</code><code style="word-wrap: normal;"><span style="color: #cc0000;"><b>06.004Z0</b></span></code><code style="color: black; word-wrap: normal;">......v.|
000000a0 74 30 72 31 0b 30 09 06 03 55 04 06 13 02 43 41 |t0r1.0...U....CA|
000000b0 31 10 30 0e 06 03 55 04 08 13 07 4f 6e 74 61 72 |1.0...U....Ontar|
000000c0 69 6f 31 0f 30 0d 06 03 55 04 07 13 06 4f 74 74 |io1.0...U....Ott|
000000d0 61 77 61 31 16 30 14 06 03 55 04 0a 13 0d 45 6e |awa1.0...U....En|
000000e0 74 72 75 73 74 2c 20 49 6e 63 2e 31 28 30 26 06 |trust, Inc.1(0&.|
000000f0 03 55 04 03 13 1f 45 6e 74 72 75 73 74 20 54 69 |.U....Entrust Ti|
00000100 6d 65 20 53 74 61 6d 70 69 6e 67 20 41 75 74 68 |me Stamping Auth|
00000110 6f 72 69 74 79 a0 82 0a 23 30 82 05 08 30 82 03 |ority...#0...0..|
<...4KB Later...>
00000e80 7a 1b a2 95 ec cc 1e d5 33 06 c3 69 61 6a a5 15 |z.......3..iaj..|
00000e90 53 0a |S.|
00000e92
$
</code></pre>
<br />
Holy cow! Our 43 byte request provoked a ~4KB response! What is this thing?<br />
<br />
Naturally, it's an ASN.1 document, just like everything else involving cryptography. <span style="color: purple;">OID 1.2.840.113549.1.7.2</span> indicates that it is PKCS#7 signed data (that crazy OID formatting again). The signed data includes:<br />
<br />
<ul>
<li>The <span style="color: #0b5394;">OID indicating a SHA1 hash</span> and the <span style="color: #38761d;">hash result</span> from our request both appear.</li>
<li><span style="color: #e69138;">OID 2.16.840.114028.10.3.5</span> indicates the Entrust (their ORG ID is 114028) timestamp policy under which this result was issued. See RFC3161(2.1.5). It seems like there should be a document describing their practices somewhere, but I can't find it.</li>
<li>Next, we find that the signed document indicates that it was created at <span style="color: #cc0000;">2019-12-21 20:08:06.004 UTC</span> (this is the whole point)</li>
<li>The value <span style="color: #7f6000; font-family: "courier new" , "courier" , monospace;"><b>01F4</b></span> indicates timestamp accuracy of 500ms. This optional field has the ability to represent seconds, milliseconds and microseconds, but this response only includes milliseconds.</li>
<li>The readable strings following the accuracy field are optional timestamp GeneralName data identifying the TSA.</li>
<li>The rest of the response (most of it, really) is PKCS#7 (signed data) overhead including the signer's signature and certificate chain.</li>
</ul>
<div>
So... Neat! We submitted a hash of some data to the TSA, and it replied with our hash, the time it saw it, and a verifiable signature. This definitely beats dropping hashes on twitter to prove you had some data at a particular time.<br />
<br />
One of the places that timestamps of this sort come up is with code signing: Unlike a live transaction (say, TLS handshake), it is possible for a code signing entity to back-date a software release. Because we generally want software builds to work forever once they're created/signed, how do you stop a signer from creating a back-dated, but apparently valid release after their signing certificate has expired or been compromised? The best answer we've got is to include a 3rd party who can be trusted to not fake the date, so software signatures might include one of these timestamps.</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-10761289288527870642019-12-14T23:19:00.001+00:002019-12-15T07:42:29.023+00:00Physically man-in-the-middling an IoT device with Linux Bridge<div style="font-stretch: normal; line-height: normal;">
<span style="font-family: inherit; font-variant-ligatures: no-common-ligatures;">This is a quick writeup of how I did some analysis of an IoT device (The Thing) by physically inserting a Linux box into the network path between The Thing and the network service it consumed. The approach described here involves being physically close to the target system, but it should work equally well<a href="https://www.blogger.com/blogger.g?blogID=3266263034124005485#1" name="top1"><sup>1</sup></a>
anywhere there's an Ethernet link along the path between The Thing and it's server.</span></div>
<span style="font-family: inherit;"><br /></span>
<br />
<div style="font-stretch: normal; line-height: normal;">
<span style="font-family: inherit; font-variant-ligatures: no-common-ligatures;">First, the topology: The Thing is attached to an Ethernet switch and is part of the 192.168.1.0/24 subnet. We'll be physically inserting ourselves into the path of the red cable in this diagram.</span><br />
<span style="font-family: inherit; font-variant-ligatures: no-common-ligatures;"><br /></span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-oV870BO6Qbk/XfVeBNlbigI/AAAAAAAAAtc/DaFiY-rKtD8668RIt4fTlecxJCOKCeCjgCLcBGAsYHQ/s1600/MITM1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1075" data-original-width="1309" height="327" src="https://1.bp.blogspot.com/-oV870BO6Qbk/XfVeBNlbigI/AAAAAAAAAtc/DaFiY-rKtD8668RIt4fTlecxJCOKCeCjgCLcBGAsYHQ/s400/MITM1.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Initial setup</td></tr>
</tbody></table>
<br />
<div style="font-stretch: normal; line-height: normal;">
<span style="font-family: inherit; font-variant-ligatures: no-common-ligatures;">The first step is to get a dual-homed Linux box into the path. I used an Ubuntu 18.04 machine with the following netplan configuration:</span><br />
<span style="font-family: inherit; font-variant-ligatures: no-common-ligatures;"><br /></span></div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: no
eth1:
dhcp4: no
bridges:
br0:
addresses: [192.168.1.2/24]
gateway4: 192.168.1.1
interfaces:
- eth0
- eth1
</code></pre>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>
<span style="font-variant-ligatures: no-common-ligatures;"></span><br />
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">This configuration defines an internal software-based bridge for handling traffic between The Thing and the switch. Additionally, it creates an IP interface for the Linux host to communicate with neighbors attached to the bridge (everybody on 192.168.1.0/24.) The Thing's TCP connection to the server is uninterrupted, even with the MITM box cabled inline like this:</span></span></div>
</div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-VTWbS3LAUwo/XfVeGWEC7mI/AAAAAAAAAt0/iQwmvPEGPB0IdhhaJArlWanOAf8GXbYqwCEwYBhgL/s1600/MITM2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1049" data-original-width="1379" height="303" src="https://1.bp.blogspot.com/-VTWbS3LAUwo/XfVeGWEC7mI/AAAAAAAAAt0/iQwmvPEGPB0IdhhaJArlWanOAf8GXbYqwCEwYBhgL/s400/MITM2.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">MITM box with software bridge deployment</td></tr>
</tbody></table>
<div>
<br /></div>
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">Now traffic to and from The Thing flows through the Linux machine. Just... Like... Any other switch. Not super useful. Yet.</span></span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">We'll need some NAT rules:</span></span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span></div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> # The first rule is an ebtables (like iptables, but for bridged/L2 traffic)
# policy that rewrites frames containing northbound traffic. It's looking for:
# frames arriving on eth0 (-i eth0)
# frames containing IPv4 traffic (-p IPv4)
# frames sourced from The Thing (-s <mac-of-The-Thing>)
# frames containing packets destined for the server (--ip-destination <server-ip>)
#
# Frames matching all of those requirements, get their header rewritten
# (--to-destination <mac-of-br0>) so for delivery to the local IP subsystem
# (this box) rather than to the gateway router.
ebtables -t nat -A PREROUTING -i eth0 -p IPv4 -s <mac-of-The-Thing> --ip-destination <server-ip> -j dnat --to-destination <mac-of-br0>
# The second rule is an iptables rule that that rewrites northbound packets.
# It's looking for:
# packets arriving on the br0 IP interface (due to previous rule's dMAC rewrite)
# packets destined for the server's IP address
#
# Packets matching those reqirements get their header rewritten so that they're
# directed to a local network service, rather than the intended server on the
# Internet.
iptables -t nat -A PREROUTING -i br0 -d <server-ip> -j DNAT --to-destination 192.168.1.2
# The final rule modifies southbound traffic created by the MITM system so that
# it appears to have come from the real server on the Internet. It's an iptables
# rule looking for:
# packets leaving the br0 IP interface
# packets destined for The Thing
#
# Packets matching those requirements get their header rewritten so that they
# appear to have been created by the real server on the Internet.
iptables -t nat -A POSTROUTING -o br0 -d 192.168.1.50 -j SNAT --to-source <server-ip>
</code></pre>
<span style="font-family: inherit;"><br /></span>
<br />
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">With the rules installed, the traffic situation looks like this:</span></span></div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"> <table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-OgPh9nX91jM/XfViOvAJ8RI/AAAAAAAAAt8/EPzWhoXuShw0_8f7GMoqZWOqp4-bdlsPQCLcBGAsYHQ/s1600/MITM3%2B%25281%2529.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1172" data-original-width="1447" height="323" src="https://1.bp.blogspot.com/-OgPh9nX91jM/XfViOvAJ8RI/AAAAAAAAAt8/EPzWhoXuShw0_8f7GMoqZWOqp4-bdlsPQCLcBGAsYHQ/s400/MITM3%2B%25281%2529.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">NAT fools The Thing into talking (and listening) to the MITM</td></tr>
</tbody></table>
<span style="font-family: inherit;"><br /></span></span><br />
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">At this point, the NAT rules have broken the application because now, when the client tries to establish a connection to the server, it winds up talking to whatever's listening on the Linux box. Probably there's no listener there, so the client's </span><span style="font-family: "courier new" , "courier" , monospace;">[SYN]</span><span style="font-family: inherit;"> segment sent toward the server (and intercepted by the Linux box) provokes the MITM to respond with a </span><span style="font-family: "courier new" , "courier" , monospace;">[RST]</span><span style="font-family: inherit;"> segment.</span></span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 13px;">
<br /></div>
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">We need to create a listener to accept connections from The Thing, a client to connect to the real server, and then stitch these two processes together to get the application running again.</span></span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">If the client is sending HTTP traffic, we could use a proxy like burp/zap/fiddler to do that job. But what if it's not HTTP traffic? Or if we compulsively do things the hard way? The simplest proxy we can build here consists of back-to-back instances of </span><span style="font-family: "courier new" , "courier" , monospace;">netcat</span><span style="font-family: inherit;">. For example, if the client is connecting to the server on TCP/443 we'd do:</span></span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span></div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> # Create a pipe for southbound data:
mkfifo -p /tmp/southbound-pipe
# Start two nc instances to perform MITM byte stream relay
# between The Thing and the real server:
nc -l 443 < /tmp/southbound-pipe | nc <server-ip> 443 > /tmp/southbound-pipe
</code></pre>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>
Here's how that CLI incantation works:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-5oHPdUioU08/XfVeGckDAjI/AAAAAAAAAtw/StubrqXWnhkVA12rgjh6cDpaxP2HdeYIgCEwYBhgL/s1600/MITM4.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="523" data-original-width="1120" height="297" src="https://1.bp.blogspot.com/-5oHPdUioU08/XfVeGckDAjI/AAAAAAAAAtw/StubrqXWnhkVA12rgjh6cDpaxP2HdeYIgCEwYBhgL/s640/MITM4.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">netcat and pipes and redirection, oh my!</td></tr>
</tbody></table>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">So, rather than acting as an Ethernet bridge (layer 2), our MITM is now operating on the byte stream, somewhere around layer 5 (<a href="https://www.youtube.com/watch?v=m3dZl3yfGpc&t=9">don't think too hard about this</a>).</span></span></div>
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span></div>
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">Can the client or server detect these shenanigans?</span></span></div>
<div style="font-stretch: normal; line-height: normal;">
</div>
<ul>
<li><span style="font-family: inherit;">Both sides will believe they're talking to the usual IP address (client because of NAT trickery; server because all connections appear to come from gateway router).</span></li>
<li><span style="font-family: inherit;">The client will see impossibly fast TCP round-trip times, because the MITM is physically close. This will likely not be noticed.</span></li>
<li><span style="font-family: inherit;">Both sides will likely experience different incoming IP TTL values. Again, not likely noticed.</span></li>
<li><span style="font-family: inherit;">Finally, at the TCP layer it is likely that our MITM box will present different TCP behavior and options than the original client and server, but these will likely be interoperable and go unnoticed except via pcap analysis.</span></li>
</ul>
<br />
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">So, about that byte stream... What's in it anyway? Here's how to see inside:</span></span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span></div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> # save northbound and southbound data to files
nc -l 443 < /tmp/southbound-pipe | tee /tmp/client-data | nc <server-ip> 443 | tee /tmp/server-data > /tmp/southbound-pipe
# ...or...
# print northbound and southbound data to the terminal
nc -l 443 < /tmp/southbound-pipe | tee /dev/fd/2 | nc <server-ip> 443 | tee /dev/fd/2 > /tmp/southbound-pipe
</code></pre>
<span style="font-family: inherit;"><span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"></span>
</span><br />
<div style="font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">If the service is running on TCP/443 as in this example, we're probably going to be disappointed when we look at the intercepted data. Even though we've MITM'ed the TCP bytestream, the TLS session riding on it remains intact, so we're MITMing and relaying an encrypted byte stream.</span></span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;">We need to go deeper. If we have a certificate (and private key) trusted by the client device, we can do that by using </span><span style="font-family: "courier new" , "courier" , monospace;"><b>openssl s_client</b></span><span style="font-family: inherit;"> and </span><span style="font-family: "courier new" , "courier" , monospace;"><b>openssl s_server</b></span><span style="font-family: inherit;"> in place of </span><span style="font-family: "courier new" , "courier" , monospace;"><b>nc</b></span><span style="font-family: inherit;">:</span></span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span>
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mkfifo -p /tmp/cleartext-pipe
openssl s_server -cert cert.pem -key key.pem -port 443 < /tmp/cleartext-pipe | tee /tmp/client-data | openssl s_client -connect <server-ip>:443 | tee /tmp/server-data > /tmp/cleartext-pipe
</code></pre>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-family: inherit;"><br /></span></span></div>
</div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;">Will the client or server notice now? Because we're terminating TLS, it provides a whole new layer (keys, certificates, ciphers, etc...) where these shenanigans can be noticed and/or lead to <strike>opportunities</strike> problems.</span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>
<span style="font-variant-ligatures: no-common-ligatures;">Do you <i>need</i> to physically MITM things like this? Probably not. L</span>aunching an ARP poisoning attack would likely have led to the same result, but this approach is a little more reliable and definitely more interesting.<br />
<br /></div>
<hr width="80%" />
<span class="Apple-style-span" style="font-size: x-small;">
<a href="https://www.blogger.com/null" name="1"><b>1 </b></a>Subject to performance limitations of your Linux bridge, I guess. Don't go trying this on 100Gb/s links :)<a href="https://www.blogger.com/blogger.g?blogID=3266263034124005485#top1"><sup>↩</sup></a>
</span>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-65706261679759572742019-02-15T15:51:00.000+00:002019-02-15T15:51:02.012+00:00SSH to all of the serial portsThis is just a quick-and-dirty script for logging into every serial port on an Opengear box, one in each tab of a MacOS terminal.<br />
<br />
Used it just recently because I couldn't remember where a device console was connected.<br />
<br />
Don't change mouse focus while it's running: It'll wind up dumping keystrokes into the wrong window.<br />
<br />
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;">for i in $(seq 48)</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;">do</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;"> port=$(expr 3000 + $i)</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;"> sshcmd="ssh -p $port terminalserver"</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;"> osascript \</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;"> -e 'tell application "Terminal" to activate' \</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;"> -e 'tell application "System Events" to tell process "Terminal" to keystroke "t" using command down' \</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;"> -e "tell application \"System Events\" to tell process \"Terminal\" to keystroke \"$sshcmd\"" \</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;"> -e "tell application \"System Events\" to tell process \"Terminal\" to key code 36"</span></div>
<div style="background-color: white; font-family: menlo; font-stretch: normal; line-height: normal;">
<span style="font-size: x-small; font-variant-ligatures: no-common-ligatures;">done</span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span></div>
<div>
<br /></div>
Leaving it here in case somebody (probably me) finds it useful in the future.chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com2tag:blogger.com,1999:blog-3266263034124005485.post-31508551961724017742019-01-21T22:03:00.003+00:002019-01-21T22:03:58.670+00:00Cannot connect the virtual device ... because no corresponding device is available on the hostRecently I've been building some VM templates on my MacBook and launching instances of them in VMware. Each time it produced following error:<br />
<br />
Cannot connect the virtual device sata0:1 because no corresponding device is available on the host.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-zdW1K6bXR2M/XEY7RWtTxkI/AAAAAAAAAoI/XNDQASEvU4w9KIr29NmMfd-fcPLvdofNwCLcBGAs/s1600/Screen%2BShot%2B2019-01-17%2Bat%2B6.15.45%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="386" data-original-width="844" height="182" src="https://2.bp.blogspot.com/-zdW1K6bXR2M/XEY7RWtTxkI/AAAAAAAAAoI/XNDQASEvU4w9KIr29NmMfd-fcPLvdofNwCLcBGAs/s400/Screen%2BShot%2B2019-01-17%2Bat%2B6.15.45%2BPM.png" width="400" /></a></div>
<br />
Either button caused the guest to boot up. The "No" button ensured that it booted without error on subsequent reboots, while choosing "Yes" allowed me to enjoy the error with each power-on of the guest.<br />
<br />
Sata0 is, of course a (virtual) disk controller, and device 1 is an optical drive. I knew that much, but the exact meaning of the error wasn't clear to me, and googling didn't lead to a great explanation.<br />
<br />
I wasn't expecting there to be a "corresponding device ... available on the host" because the host has neither a SATA controller nor an optical drive, and no such hardware should be required for my use case, so, what did the error mean?<br />
<br />
It turns out that I was producing the template (a .ova file) with the optical drive "connected" (VMware term) to ... something. The issue isn't related to the lack of a <i>device</i> on the host, but that there's no ISO file "inserted" into the virtual drive.<br />
<br />
Here's the relevant stanza from the template's .ovf file:<br />
<br />
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <Item></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:AddressOnParent>1</rasd:AddressOnParent></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:AutomaticAllocation>true</rasd:AutomaticAllocation></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:Caption>cdrom1</rasd:Caption></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:Description>CD-ROM Drive</rasd:Description></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:ElementName>cdrom1</rasd:ElementName></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:InstanceID>7</rasd:InstanceID></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:Parent>5</rasd:Parent></span></div>
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> <rasd:ResourceType>15</rasd:ResourceType></span></div>
<br />
<div style="background-color: white; font-family: Menlo; font-size: 11px; font-stretch: normal; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"> </Item></span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;">The problem here is the AutomaticaAllocation element. AutomaticAllocation is VMware's "connect at boot" feature, which really boils down to "insert a disk into this virtual drive". Without specifying a backend device and/or file, it can't be connected.</span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;">Deleting the element, or setting it to "false" fixes the problem.</span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span></div>
<div>
AddressOnParent: 1 <- This makes it sata0:1 instead of sata0:0</div>
<div>
InstanceID: 7 <- This device is the 8th hardware device defined for the guest</div>
<div>
Parent: 5 <- This device is a child of the hardware device at instance id #5 (the sata0)</div>
<div>
ResourceType: 15 <- This is an optical drive</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com1tag:blogger.com,1999:blog-3266263034124005485.post-39562290236116104272017-11-11T16:21:00.001+00:002018-02-20T18:19:34.236+00:00Syslog relay with ScapyI needed to point some syslog data at a new toy being evaluated by security folks.<br />
<div>
<br /></div>
<div>
Reconfiguring the logging sources to know about the new device would have been too much of a hassle for a quick test. Reconfiguring the Real Log Server (an rsyslog box) to relay the logs wasn't viable because the source IP in the syslog packets would have reflected the syslog box instead of the origin server.</div>
<div>
<br /></div>
<div>
A few lines of python running on the existing rsyslog box did the trick:</div>
<div>
<br /></div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> #!/usr/bin/env python2.7
from scapy.all import *
def pkt_callback(pkt):
del pkt[Ether].src
del pkt[Ether].dst
del pkt[IP].chksum
del pkt[UDP].chksum
pkt[IP].dst = '192.168.100.100'
sendp(pkt)
sniff(iface='eth0', filter='udp port 514', prn=pkt_callback, store=0)
</code></pre>
<div>
<br />
This script has scapy collecting frames matching <span style="font-family: "courier new" , "courier" , monospace;"><b>udp port 514</b></span> (libpcap filter) from interface eth0. Each matching packet is handed off to the <span style="font-family: "courier new" , "courier" , monospace;"><b>pkt_callback</b></span> function. It clears fields which need to be recalculated, changes the destination IP (to the address of the new Security Thing) and puts the packets back onto the wire.<br />
<br />
The source IP on these forged packets is unchanged, so the Security Thing thinks it's getting the original logs from real servers/routers/switches/PDUs/weather stations/printers/etc... around the environment.<br />
<br />
I'd expected to need to filter out the packets that scapy is sending (don't listen to and re-send your own noise), but that doesn't seem to have been necessary.</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com2tag:blogger.com,1999:blog-3266263034124005485.post-35351129559551220012017-10-05T16:18:00.000+01:002017-10-05T16:25:04.136+01:00SSH HashKnownHosts File FormatThe HashKnownHosts option to the OpenSSH client causes it obfuscate the host field of the ~/.ssh/known_hosts file. Obfuscating this information makes it harder for threat actors (malware, border searches, etc...) to know which hosts you connect to via SSH.<br />
<br />
Hashing defaults to off, but some platforms turn it on for you:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris:~$ <b>grep Hash /etc/ssh/ssh_config</b>
HashKnownHosts yes
chris:~$
</code></pre>
<div>
<br /></div>
<div>
Here's an entry from my known_hosts file:<br />
<br /></div>
<div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> |1|NWpzcOMkWUFWapbQ2ubC4NTpC9w=|ixkHdS+8OWezxVQvPLOHGi2Oawo= ecdsa-sha2-nistp256 AAAAE2Vj<...>ZHNLpyJsv
</code></pre>
<br />
There's one record per line, with the fields separated by spaces. The first field is the remote host (SSH server) identifier.<br />
<br />
In this case, the leading characters <span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">|1|</span> in the host identifier are the magic string (HASH_MAGIC). It tells us that the field is hashed, rather than a plaintext hostname (or address). The remaining characters in the field comprise two parts: a 160-bit salt (random string) and a 160-bit SHA1 hash result. Both values are base64 encoded.<br />
<br />
The various OpenSSH binaries that use information in this file feed both the remote hosts name (or address) and the salt to the hashing function in order to produce the hash result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-0AI8Tzsq4XM/WdZF_xGOucI/AAAAAAAAAg0/mdCJpRi09WoS8qewmuy7WkIrG4Gek_wkgCLcBGAs/s1600/hash_known_hosts.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="169" data-original-width="524" height="128" src="https://3.bp.blogspot.com/-0AI8Tzsq4XM/WdZF_xGOucI/AAAAAAAAAg0/mdCJpRi09WoS8qewmuy7WkIrG4Gek_wkgCLcBGAs/s400/hash_known_hosts.png" width="400" /></a></div>
<br />
So, lets validate a host entry against this record the hard way. The entry above is for an IP address: 10.0.0.1.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris:~$ <b>host="10.0.0.1"</b>
chris:~$ <b>salt_from_file="NWpzcOMkWUFWapbQ2ubC4NTpC9w="</b>
chris:~$ <b>salt_hexdump=$(echo $salt_from_file | base64 --decode | xxd -p)</b>
chris:~$ <b>echo -n $host | openssl sha1 -binary -mac HMAC -macopt hexkey:$salt_hexdump | base64</b>
ixkHdS+8OWezxVQvPLOHGi2Oawo=
chris:~$
</code></pre>
<br />
The resulting string (<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">ixkHdS+8OWezxVQvPLOHGi2Oawo=</span>) is the base64 encoded hash result produced by inputting our host IP and the salt we found in the file. It's the same string that we saw in the <span style="font-family: "courier new" , "courier" , monospace;">known_hosts</span> entry, so we know that this entry is for the host 10.0.0.1.<br />
<br />
When adding a new record to <span style="font-family: "courier new" , "courier" , monospace;">known_hosts</span>, the salt is a random value invented on the spot. The hash is calculated and the salt, hash and key details are written to the file.<br />
<br />
When trying to find a record in an existing known_hosts file, the SSH program can't pick the right line directly. Instead it has to take the hostname (address) it's looking for, and compute the hash using the salt found on each line. When (if) it finds a match, then that's the line it was looking for. SHA1 happens pretty fast on modern hardware, but depending on your use case, this may be a bunch of wasted effort, particularly on systems where there's no point in obfuscating the list of SSH servers to which we connect.<br />
<br />
<br />
<br />
<div style="text-align: center;">
<span style="font-size: xx-small;"><a href="https://icons8.com/">These folks</a> drew the cocktail shaker.</span></div>
</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com2tag:blogger.com,1999:blog-3266263034124005485.post-38566326032575737192017-09-26T19:52:00.000+01:002017-09-27T01:45:41.861+01:00Pluribus Networks... Wait, where are we again?<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-MN_yi7v8h9Q/WcqUSKuMshI/AAAAAAAAAgM/cc8T5UZV0Bk9RIBBRlXTHWuxkCRSL0-dQCLcBGAs/s1600/cropped.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="306" data-original-width="424" height="230" src="https://1.bp.blogspot.com/-MN_yi7v8h9Q/WcqUSKuMshI/AAAAAAAAAgM/cc8T5UZV0Bk9RIBBRlXTHWuxkCRSL0-dQCLcBGAs/s320/cropped.png" width="320" /></a></div>
<a href="https://2.bp.blogspot.com/-GGr6uMfsrb8/WcqT7Mm6whI/AAAAAAAAAgI/xmAnGQI-KTsb7HpefmF8fw9Wrdv2szoiwCLcBGAs/s1600/Slide1.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><br /></a>
I was privileged to visit <a href="http://www.pluribusnetworks.com/">Pluribus Networks</a> as a delegate at <a href="http://techfieldday.com/event/nfd16/">Network Field Day 16</a> a couple of weeks ago. Somebody else paid for the trip. Details <a href="http://www.fragmentationneeded.net/p/gestalt-it.html">here</a>.<br />
<br />
Much has changed at Pluribus, I hardly recognized the place!<br />
<br />
I quite like Pluribus (their use of Solaris under their Netvisor switching OS got me right in the feels early on) so I'm happy to report that most of what's new looks like changes for the better.<br />
<br />
When we arrived at Pluribus HQ we were greeted by some new faces, a new logo, color scheme... Even new accent lighting in the demo area!<br />
<br />
Gone also are the Server Switches with their monstrous control planes (though <a href="http://www.pluribusnetworks.com/products/e-series/">still listed on the website</a>, they weren't mentioned in the presentation), Solaris, and a partnership with Supermicro.<br />
<br />
In their place we found:<br />
<br />
<ul>
<li>The new logo and colors</li>
<li>New faces in management and marketing</li>
<li>Netvisor running on Linux</li>
<li>Whitebox and OCP-friendly switches</li>
<li>A partnership with D-Link</li>
<li>Some Netvisor improvements</li>
</ul>
<h3>
Linux</h3>
<div>
This was probably inevitable, and likely matters little to Netvisor users. When Pluribus was first getting off the ground, I was waiting for an OpenSolaris release that never happened. That Pluribus stuck with Solaris for as long as they did while Oracle was dismantling the Solaris ecosystem is kind of incredible. Netvisor on Linux is fine, I'm sure.</div>
<div>
<br /></div>
<h3>
Switch Hardware</h3>
<div>
One of Pluribus' claims to fame was their "server switches". These were normal switches using merchant switching silicon (from 2 or 3 different vendors, if I recall... I think Netvisor has a hardware abstraction layer which allows them to switch easily between Broadcom/Intel/Mellanox ASICs), but with enormous control planes sporting lots of cores, lots of RAM, lots of storage, dedicated network processors, etc...</div>
<div>
<br /></div>
<div>
The big switches opened the door to some interesting possibilities, but likely made a tough sell to customers that just wanted an IP network fabric. Which is probably <i>most customers.</i></div>
<div>
<br /></div>
<div>
These days Pluribus is selling vanilla-looking Open Compute-friendly switches with ONIE, and supporting Netvisor on a handful of 3rd party whitebox platforms.</div>
<div>
<br /></div>
<h3>
That D-Link Partnership</h3>
<div>
Okay, quit laughing. The D-Link switch in question is Trident II based, just like (almost) every other switch in the market. If D-Link helps Pluribus move product, then I'm delighted for all involved. The only thing I don't like about the DXS-5000-54S is that it lacks an RS-232 port. USB console? Ugh. I'll run my Netvisors on something with a proper management interface, <i>thankyouverymuch</i>.</div>
<div>
<br /></div>
<h3>
Netvisor</h3>
<div>
Netvisor still looks pretty great! Some standout features:</div>
<div>
<ul>
<li>Netvisor uses standard protocols to interact with neighboring devices, but you manage a Netvisor fabric as a single device.</li>
<li>It's still got fantastic telemetry and flow analytics capabilities, even without the monstrous control plane. Some slightly outrageous claims were made in this area toward the end of the presentation, but we didn't have time to dig in.</li>
<li>Individual nodes are managed in-band (via the front-panel interfaces, rather than the management LAN port). Incredibly this capability is not universal in this product space. Some platforms rely on the lone management Ethernet interface for fabric control purposes. This fact blows my mind. I'm similarly surprised that whitebox switches don't tend to come with redundant control plane paths. Maybe there's a single "eth0" port baked into the Trident chip for this purpose?</li>
<li>Routing is performed by an anycast gateway. That is, moving packets from one broadcast domain to another <i>does not</i> require them to be hauled to a certain point in the fabric. Any Netvisor switch (the <i>nearest</i> Netvisor switch) will do the job. This is a welcome change.</li>
<li>Members of a Netvisor fabric don't need to be cabled to one another. This opens the door to using Netvisor only at the leaf tier in a leaf/spine fabric... Or only at the spine... Or at both layers as a single large fabric... Or at both layers, but as two fabrics (one for leaf, one for spine)... Or as smaller deployment units in a <i>huge</i> fabric. Lots of possibilities here.</li>
</ul>
</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-19449516100919588042017-09-23T03:17:00.001+01:002017-11-12T21:07:20.730+00:00KEMP Presented Some Interesting Features at NFD16<a href="https://upload.wikimedia.org/wikipedia/en/f/ff/KEMP_Application_Delivery_Logo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="207" data-original-width="481" height="137" src="https://upload.wikimedia.org/wikipedia/en/f/ff/KEMP_Application_Delivery_Logo.png" width="320" /></a>KEMP Technologies presented at Network Field Day 16, where I was privileged to be a delegate. Who paid for what? Answers <a href="http://www.fragmentationneeded.net disclaimer">here</a>.<br />
<br />
<br />
Three facets of the KEMP presentation stood out to me:<br />
<h4>
<b><br /></b></h4>
<h4>
<b>The KEMP Management UI Can Manage Non-KEMP Devices</b></h4>
KEMP's centralized management UI, the KEMP 360 Controller, can manage/monitor other load balancers (ahem, <i>Application Delivery Controllers</i>) including AWS ELB, HAProxy, NGINX and F5 BIG-IP.<br />
<br />
This is pretty clever: If KEMP gets into an enterprise, perhaps because it's dipping a toe into the cloud at Azure, they may manage to worm their way deeper than would otherwise have been possible. Nice work, KEMPers.<br />
<br />
<h4>
VS Motion Can Streamline Manual Deployment Workflows</h4>
KEMP's VS Motion feature allows easy service migrations between KEMP instances by copying service definitions from one box to another. It's probably appropriate when replicating services between production instances and when promoting configurations between dev/test/prod. The mechanism is described in some detail here:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/LdyGCyedQuc/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/LdyGCyedQuc?feature=player_embedded" width="320"></iframe></div>
<br />
The interface is pretty straightforward. It looks just like the balance transfer UI at my bank: Select the <b>From</b> instance, the <b>To</b> instance, what you want transferred (which virtual service) and then hit the <b>Move</b> button. The interface also sports a <b>Copy</b> button, so in that regard it's better than the UI at the bank. I look forward to the bank allowing me to replicate funds between accounts in the future :)<br />
<br />
I think it struck all of the Network Field Day delegates that this feature is primarily useful for manual workflows. An automated workflow wouldn't need an "easy button" like the VS Motion feature. Unfortunately there wasn't enough time to get into KEMP's Automation/API capabilities during the presentation, but <a href="https://twitter.com/packetologist">Keith Miller</a> was tuned into the live stream and reported that the API is a pleasure to use:<br />
<center>
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
The API for KEMP is very easy to work with. I’m a Python newb & was able to script something easily to change a setting in all VSs <a href="https://twitter.com/hashtag/NFD16?src=hash">#NFD16</a></div>
— Keith Miller (@packetologist) <a href="https://twitter.com/packetologist/status/908400272719974402">September 14, 2017</a></blockquote>
</center>
<i>Update from Keith:</i><br />
<center>
<blockquote class="twitter-tweet" data-lang="en">
<div dir="ltr" lang="en">
Good read! I'll admit I was caught off guard by the mention of my tweet. The one thing I'll say now that I've learned a little more about APIs is that I wish the output was in a JSON format so you don't have to webscrape the response.</div>
— Keith Miller (@packetologist) <a href="https://twitter.com/packetologist/status/929788555328741377">November 12, 2017</a></blockquote></center>
<script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script>
<br />
It's disappointing to read that the API doesn't return structured data.<br />
<br />
<script async="" charset="utf-8" src="//platform.twitter.com/widgets.js"></script>VS Motion does not, as I understand it, have the ability to copy TLS certificates around right now, but the feature request is in.<br />
<br />
<h4>
That Strange License</h4>
Frankly, this topic from the NFD16 presentation doesn't make much sense to me.<br />
<br />
When you're buying <i>boxes</i>, or even virtual capabilities that are licensed by a bandwidth cap, you're going to have paid-for-but-wasted capacity during off-peak times. KEMP has introduced a consumption-based model to work around that problem: Pay only for what you use!<br />
<br />
It sounds great, especially with the popularity of virtual services. When talking about physical boxes, it makes sense that you'd have to pay for any overcapacity you may have provisioned: There's the box, 95% idle, waiting for that peak traffic day... Full of expensive processors and RAM... Oh, and there's the failover box, at 100% idle... You probably didn't expect to get the hardware for free, right?<br />
<br />
The situation <i>feels different</i> when we're talking about virtual appliances: How much would you expect to pay for a <i>virtual</i> standby server? One which, if everything goes according to plan, will <i>never</i> see a request from a live client? You're already paying somebody else (the server vendor or IaaS provider) for the hardware, so paying KEMP based on <i>usage</i> seems ideal.<br />
<br />
But they've created an altogether new problem: KEMP's consumption based license model finds the peak throughput (at 5 minute intervals) of each participating node, then <i>adds them up</i> to calculate the monthly bill.<br />
<br />
Let's imagine that your organization has a rock-steady 1Gb/s flow rate through an active/standby pair of KEMP boxes, plus a DR facility somewhere.<br />
<br />
Every month you pay for 1Gb/s of usage.<br />
<br />
Then one day the active unit fails, load switches to the standby unit. Several hours later, you shift workload to the DR site while performing maintenance to restore the failed hardware in the main site.<br />
<br />
Take the peak throughput from each KEMP unit: Active (failed), Standby (now active) and DR have each hit 1Gb/s. That month you'll pay for 3Gb/s, even though the workload never changed. You just moved it around.<br />
<br />
It seems like anybody with any degree of workload mobility will be overpaying with this model, unless the per-bandwidth price is also quite low.<br />
<br />
I'd be much more comfortable paying per byte, per TLS setup or per load-balanced request. The sum-of-peaks model seems too unpredictable to me.chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-54532241039198100942017-08-31T22:18:00.001+01:002017-08-31T22:18:18.946+01:00Using FQDN for DMVPN hubsI've done some testing with specifying DMVPN hubs (NHRP servers, really) using their DNS name, rather than IP address.<br />
<br />
This matters to me because of some goofy environments where spoke routers can't predict what network they'll be on (possibly something other than internet), and where I can't leverage multiple hubs per tunnel due to a control plane scaling issue.<br />
<br />
The DNS-based configuration includes the following:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> interface Tunnel1
ip nhrp nhs dynamic nbma <i>dmvpn-pool.fragmentationneeded.net</i>
</code></pre>
<br />
There's no longer a requirement for any <b><span style="font-family: Courier New, Courier, monospace;">ip nhrp map</span></b> or <span style="font-family: Courier New, Courier, monospace;"><b>ip nhrp nhs x.x.x.x</b></span> configuration when using this new capability.<br />
<br />
My testing included some tunnels with very short ISAKMP and IPSec re-key intervals. I found that the routers performed the DNS resolution just once. They didn't go back to DNS again for as long as the hub was reachable.<br />
<br />
Spoke routers which failed to establish a secure connection for whatever reason would re-resolve the hub address each time the DNS response expired its TTL. But once they succeeded in connecting, I observed no further DNS traffic for as long as the tunnel survived.<br />
<br />
The record I published (dmvpn-pool.fragmentationneeded.net above) includes multiple A records. The DNS server randomizes the record order in its responses and spoke routers always connected to the <i>first</i> address on the list.<br />
<br />
The random-ordered DNS response makes for a kind of nifty load balancing and failover capability:<br />
<br />
<ol>
<li>The spokes will naturally balance across the population of hubs, depending on the whim of the DNS server</li>
<li>I don't strictly need a smart (GSLB style) DNS server to effect failover, because spokes will <i>eventually</i> find their way to a working hub, even with bad records in the list.</li>
</ol>
<br />
<br />
With 3 hub routers, the following happens when one fails:<br />
<br />
<ul>
<li>At T=0, 67% of the routers remain connected.</li>
<li>At T=<keepalive>s, 89% of routers are connected (2/3 of the orphans are back online. The others are trying the dead hub again).</li>
<li>At T=TTLx1, 96% of routers are connected (1/3 of the orphans from the previous interval tried the dead hub a second time)</li>
<li>At T=TTLx2, 99% of routers are back online</li>
</ul>
<div>
Things recover fairly quickly with short TTL intervals, even without a GSLB because the spokes <i>keep trying</i>, and only need to find a working record once. This DMVPN tunnel isn't the only path in my environment, so a couple of minutes outage is acceptable.</div>
<br />
<br />
A 60 second TTL will result in ~40K queries/month for each spoke that can't connect (problems with firewall, overload NAT, credentials, etc...), so watch out for that if you're using a service that causes you to pay per query :)chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com1tag:blogger.com,1999:blog-3266263034124005485.post-59954527217995572412017-08-30T16:18:00.000+01:002017-08-30T17:08:48.320+01:00Small Site Multihoming with DHCP and Direct Internet AccessCisco recently (15.6.3M2 ) resolved CSCve61996, which makes it possible to fail internet access back and forth between two DHCP-managed interfaces in two different front-door VRFs attached to consumer-grade internet service.<br />
<br />
Prior to the IOS fix there was a lot of weirdness with route configuration on DHCP interfaces assigned to VRFs.<br />
<br />
I'm using a C891F-K9 for this example. The WAN interfaces are Gi0 and Fa8. They're in F-VRF's named ISP_A and ISP_B respectively:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://2.bp.blogspot.com/-mER7dqNlHvI/WaXPFixvnkI/AAAAAAAAAfM/86QzOcQ-Cf8-wpssRTvYrT53v6hdKT8XQCLcBGAs/s1600/DHCP_Multihoming.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="436" data-original-width="497" height="350" src="https://2.bp.blogspot.com/-mER7dqNlHvI/WaXPFixvnkI/AAAAAAAAAfM/86QzOcQ-Cf8-wpssRTvYrT53v6hdKT8XQCLcBGAs/s400/DHCP_Multihoming.png" width="400" /></a></div>
<br />
First, create the F-VRFs and configure the interfaces:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> ip vrf ISP_A
ip vrf ISP_B
interface GigabitEthernet8
ip vrf forwarding ISP_A
ip dhcp client default-router distance 10
ip address dhcp
interface FastEthernet0
ip vrf forwarding ISP_B
ip dhcp client default-router distance 20
ip address dhcp
</code></pre>
<br />
The distance commands above assign the AD of the DHCP-assigned default route. Without these directives the distance would be 254 in each VRF. They're modified here because we'll be using the distance to select the preferred internet path when both ISPs are available.<br />
<br />
Next, let's keep track of whether or not the internet is working via each provider. In this case I'm pinging 8.8.8.8 via both paths, but this health check can be whatever makes sense for your situation. So, a couple of IP SLA monitors and track objects are in order:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> ip sla 1
icmp-echo 8.8.8.8
vrf ISP_A
threshold 500
timeout 1000
frequency 1
ip sla schedule 1 life forever start-time now
track 1 ip sla 1
ip sla 2
icmp-echo 8.8.8.8
vrf ISP_B
threshold 500
timeout 1000
frequency 1
ip sla schedule 2 life forever start-time now
track 2 ip sla 2
</code></pre>
<br />
Ultimately we'll be withdrawing the default route from each VRF when we determine that the internet has failed. This is introduces a problem: With the default route missing the SLA target will be unreachable. The SLA (and track) will <i>never</i> recover, so the default route will never be restored. So first let's add a static route to our SLA target in each VRF. The default route will get withdrawn, but the host route for the SLA target will persist in each VRF.<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> ip route vrf ISP_A 8.8.8.8 255.255.255.255 dhcp 50
ip route vrf ISP_B 8.8.8.8 255.255.255.255 dhcp 60
</code></pre>
<br />
We used the dhcp keyword as a stand-in for the next-hop IP address. We <i>could</i> have just specified the interface, but specifying a multiaccess interface without a neighbor ID is an ugly practice and assumes that proxy ARP is available from neighboring devices. Not a safe assumption.<br />
<br />
Finally, we can set the default route to be withdrawn when the track object goes down:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> interface GigabitEthernet8
ip dhcp client route track 1
interface FastEthernet0
ip dhcp client route track 2
</code></pre>
<br />
At this point, when everything is healthy, the routing table for ISP_A looks something like this:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> S* 0.0.0.0/0 [10/0] via 192.168.1.126
8.0.0.0/32 is subnetted, 1 subnets
S 8.8.8.8 [50/0] via 192.168.1.126
192.168.1.0/24 is variably subnetted, 2 subnets, 2 masks
C 192.168.1.64/26 is directly connected, GigabitEthernet8
L 192.168.1.67/32 is directly connected, GigabitEthernet8
</code></pre>
<br />
The table for ISP_B looks similar, but with different Administrative Distances. On failure of the SLA/track the default route gets withdrawn but the 8.8.8.8/32 route persists. That looks like this:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> 8.0.0.0/32 is subnetted, 1 subnets
S 8.8.8.8 [50/0] via 192.168.1.126
192.168.1.0/24 is variably subnetted, 2 subnets, 2 masks
C 192.168.1.64/26 is directly connected, GigabitEthernet8
L 192.168.1.67/32 is directly connected, GigabitEthernet8
</code></pre>
<br />
When the ISP is healed, the 8.8.8.8/32 ensures that we'll notice, the SLA will recover, and the default route will be restored.<br />
<br />
Okay, now it's time to think about leaking these ISP_A and ISP_B routes into the global routing table (GRT). First, we need an interface in the GRT for use by directly connected clients:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> interface Vlan10
ip address 10.10.10.1 255.255.255.0
</code></pre>
<br />
And now the leaking configuration:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> ip prefix-list PL_DEFAULT_ONLY permit 0.0.0.0/0
route-map RM_IMPORT_TO_GRT permit
match ip address prefix-list PL_DEFAULT_ONLY
global-address-family ipv4
route-replicate from vrf ISP_A unicast static route-map RM_IMPORT_TO_GRT
route-replicate from vrf ISP_B unicast static route-map RM_IMPORT_TO_GRT
</code></pre>
<br />
The configuration above leaks only the default route from each F-VRF. The GRT will be offered both routes and will make its selection based on the AD we configured earlier (values 10 and 20).<br />
<br />
Here's the GRT with everything working:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> S* + 0.0.0.0/0 [10/0] via 192.168.1.126 (ISP_A)
10.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C 10.10.10.0/24 is directly connected, Vlan10
L 10.10.10.1/32 is directly connected, Vlan10
</code></pre>
<br />
When the ISP_A path fails, the GRT fails over to the higher distance route via ISP_B:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> S* + 0.0.0.0/0 [20/0] via 192.168.1.62 (ISP_B)
10.0.0.0/8 is variably subnetted, 2 subnets, 2 masks
C 10.10.10.0/24 is directly connected, Vlan10
L 10.10.10.1/32 is directly connected, Vlan10
</code></pre>
<br />
Strictly speaking, it's not necessary to have the SLA monitor, track object and conditional routing in VRF ISP_B. All of those things could be omitted and the GRT would still fail back and forth between the different F-VRFs based only on the tests in "A". But I like the symmetry.<br />
<br />
Okay, so now that we've got the GRT's default route flopping back and forth between these two front-door VRFs, we'll need some NAT. First, enable NVI mode on each interface in the transit path:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> interface GigabitEthernet8
ip nat enable
interface FastEthernet0
ip nat enable
interface Vlan10
ip nat enable
</code></pre>
<br />
Next we'll spell out exactly what's going to get NATted. I like to use route-maps rather than ACLs because the templating is easier when we're matching interfaces rather than ip prefixes:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> route-map RM_NAT->ISP_A permit 10
match interface GigabitEthernet8
route-map RM_NAT->ISP_B permit 10
match interface FastEthernet0
ip nat source route-map RM_NAT->ISP_A interface GigabitEthernet8 overload
ip nat source route-map RM_NAT->ISP_B interface FastEthernet0 overload
</code></pre>
<br />
That's basically it. The last thing that might prove useful is to automate purging of NAT translation tables when switching between providers. TCP flows can't survive the ISP switchover, and clearing the NAT translations for active flows should make them fail faster than they might have otherwise.chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com3tag:blogger.com,1999:blog-3266263034124005485.post-85589279730747497742017-06-17T16:50:00.002+01:002017-06-17T16:50:34.188+01:00Serial Pinout for APCThis is just a quick note to remind me how to make serial cables for APC power strips. This cable works between an APC AP8941 and an Opengear terminal server with Cisco-friendly (-X2 in Opengear nomenclature) pinout.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://1.bp.blogspot.com/-iGMwDjFpc1s/WUVOR7MmmPI/AAAAAAAAAeg/KdWrVwEkZEsLDZcAkR3netOTYaa6J-IDQCLcBGAs/s1600/IMG_3489.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1200" height="320" src="https://1.bp.blogspot.com/-iGMwDjFpc1s/WUVOR7MmmPI/AAAAAAAAAeg/KdWrVwEkZEsLDZcAkR3netOTYaa6J-IDQCLcBGAs/s320/IMG_3489.JPG" width="240" /></a></div>
<br />
Only pins 3,4 and 6 are populated on the 8P8C end. It probably doesn't matter whether the ground pin (black) lands on pin 4 or 5 because both should be ground on the Opengear end. The yellow wire is unused.chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com5tag:blogger.com,1999:blog-3266263034124005485.post-58674178810859126052017-03-21T22:30:00.000+00:002017-03-28T17:18:42.594+01:00Cisco: Not Serious About Network Programmability<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-72jCgHY5618/WNGHe7VuzDI/AAAAAAAAAdE/gcUO54iEoYgDaSc1iUBOzL3nVExscyxUwCEw/s1600/mb.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="222" src="https://1.bp.blogspot.com/-72jCgHY5618/WNGHe7VuzDI/AAAAAAAAAdE/gcUO54iEoYgDaSc1iUBOzL3nVExscyxUwCEw/s320/mb.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://www.youtube.com/watch?v=G_Sy6oiJbEk">"You can't fool me, there ain't no sanity clause!"</a></td></tr>
</tbody></table>
Cisco isn't known for providing easy programmatic access to their device configurations, but has recently made some significant strides in this regard.<br />
<br />
The REST API plugin for newer ASA hardware is an example of that. It works fairly well, supports a broad swath of device features, is beautifully documented and has an awesome interactive test/dev dashboard. The dashboard even has the ability to spit out example code (java, javascript, python) based on your point/click interaction with it.<br />
<br />
It's really slick.<br />
<br />
<h4>
But I Can't Trust It</h4>
Here's the problem: It's an un-versioned REST API, and the maintainers don't hesitate to change its behavior between minor releases. Here's what's different between <a href="http://www.cisco.com/c/en/us/td/docs/security/asa/api/13/asa-api-rn-13.html?referring_site=RE&pos=2&page=http://www.cisco.com/c/en/us/td/docs/security/asa/api/qsg-asa-api.html#pgfId-135093">1.3(2) and 1.3(2)-100</a>:<br />
<br />
<div style="border: 0px; color: #58585b; font-family: ciscosans, arial, sans-serif; font-style: normal; font-weight: 300; letter-spacing: normal; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; text-indent: 0px; text-transform: none; vertical-align: baseline; white-space: normal; word-spacing: 0px;">
<h4 class="p_H2" style="border: 0px; font-family: inherit; font-style: inherit; font-weight: 400; line-height: 1.2em; margin: 15px 0px 10px; overflow: visible; padding: 0px; vertical-align: baseline; word-wrap: break-word;">
<span style="font-size: x-small;">
New Features in ASA REST API 1.3(2)-100</span></h4>
<div class="DD-DocumentDates" style="border: 0px; color: #58585b; font-family: inherit; font-style: inherit; font-weight: 300; line-height: 1.375em; margin: 0px 0px 6px; overflow: visible; padding: 0px; vertical-align: baseline;">
<span style="font-size: x-small;"><a href="https://www.blogger.com/null" name="pgfId-135663" style="border: 0px; color: #007fab; font-family: inherit; font-style: inherit; font-weight: 400; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; text-decoration: none; vertical-align: baseline;"></a><b class="cBold" style="border: 0px; color: #525252; font-family: inherit; font-style: inherit; font-weight: 400; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; vertical-align: baseline;">Released: </b>February 16, 2017</span></div>
<div class="pB1_Body1" style="border: 0px; color: #525252; font-family: inherit; font-style: inherit; font-weight: normal; line-height: 1.44em; margin: 0px 0px 6px; overflow: visible; padding: 5px 0px; vertical-align: baseline;">
<span style="font-size: x-small;"><a href="https://www.blogger.com/null" name="pgfId-135664" style="border: 0px; color: #007fab; font-family: inherit; font-style: inherit; font-weight: 400; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; text-decoration: none; vertical-align: baseline;"></a>As a result of the fix for <span class="cXref_Color" style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; vertical-align: baseline; word-wrap: break-word;"><a class="URL" href="http://tools.cisco.com/bugsearch/bug/CSCvb21388" style="border: 0px; color: #6f53bc; font-family: inherit; font-style: inherit; font-weight: 400; line-height: inherit; margin: 0px; overflow: visible; padding: 0px; text-decoration: none; vertical-align: baseline; word-wrap: break-word;">CSCvb21388</a></span>, the response type of /api/certificate/details was changed from the CertificateDetails object to a list of CertificateDetails. Scripts utilizing this API will need to be modified accordingly.</span></div>
</div>
<br />
So, any code based on earlier documentation is now broken when it calls <span style="font-family: "courier new" , "courier" , monospace;">/api/certificate/details</span>.<br />
<br />
<h4>
</h4>
<h4>
This Shouldn't Happen</h4>
Don't take my word for it:<br />
<br />
<hr />
<br />
<span style="background-color: white; color: #666666; font-family: "open sans" , "arial" , sans-serif; font-size: 14px;"><a href="https://codeplanet.io/principles-good-restful-api-design/">Remember than an API is a published contract between a Server and a Consumer. If you make changes to the Servers API and these changes break backwards compatibility, you will break things for your Consumer and they will resent you for it. </a></span><br />
<br />
<hr />
<div style="background-color: white; border: 0px; color: #2b2b2b; font-family: Lato, sans-serif; font-size: 16px; margin-bottom: 24px; outline: 0px; padding: 0px; vertical-align: baseline;">
<br />
<a href="https://www.narwhl.com/2015/03/the-ultimate-solution-to-versioning-rest-apis-content-negotiation/">Versioning your API is terrifying. If you push out a “breaking change” – basically any change that runs counter to what client developers have planned for, such as renaming or deleting a parameter or changing the format of the response – you run the risk of bringing down many, if not all, of your customers’ systems, leading to angry support calls or – worse – massive churn. For this reason, versioning is the number one concern among the development teams I work with when helping them design their APIs.</a></div>
<div>
<hr />
<div style="color: #7f8186; font-family: 'Martel Sans'; font-size: 14px; margin-bottom: 25px; padding-top: 0px;">
<br />
<a href="https://tyk.io/2017/02/23/when-and-how-do-you-version-your-api/">Breaking changes include:</a></div>
<ol style="color: #7f8186; font-family: 'Martel Sans'; font-size: 14px; margin: 1em 0px 25px 8px; padding: 0px 0px 0px 16px;">
<li><a href="https://tyk.io/2017/02/23/when-and-how-do-you-version-your-api/">Renaming fields and/or resource paths – often for clarity after your API is released</a></li>
<li><a href="https://tyk.io/2017/02/23/when-and-how-do-you-version-your-api/">Changing payload structures to accommodate the following: renaming or removing fields (even if they are considered optional – contracts!); changing fields from a single value to a one-to-many relationship (e.g. moving from one email address per account to a list of email addresses for an account)</a></li>
<li><a href="https://tyk.io/2017/02/23/when-and-how-do-you-version-your-api/">Fixing poor choices of HTTP verbs, response codes, or inconsistent design across your API endpoints</a></li>
</ol>
<div style="color: #7f8186; font-family: 'Martel Sans'; font-size: 14px; margin-bottom: 25px; padding-top: 0px;">
<a href="https://tyk.io/2017/02/23/when-and-how-do-you-version-your-api/">In short, once you release your API into the wild, you have to live with it. If you encounter one or more of the items above, it may be time to version your API to prevent breaking your existing API consumers.</a></div>
</div>
<hr />
<div>
<br />
<h3>
It Gets Worse</h3>
Not only does the API fail to provide consistently formatted responses, it doesn't even provide a way to discover its version. Cisco advised me to scrape the 'show version' CLI output in order to divine the correct way to parse the API's responses. Whenever they decide to change things.<br />
<br />
The irony of having to abandon the API for screen scraping <i>in order to improve API compatibility</i> is almost too much to bear. Lets assume for the moment that I'm willing to do it. Will the regex that finds the API version today still work on tomorrow's release? Do I even know how to parse the version numbers?<br />
<br />
What's the version number of the current release anyway?<br />
<br />
<ul>
<li>1.3(2)-100 (according to the release notes above)</li>
<li>1.3.2.100 (according to <span style="font-family: "courier new" , "courier" , monospace;">show version</span> CLI output)</li>
<li>1.3.2 (according to the 'release:' field on the download page)</li>
</ul>
<div>
This does not look like a road I'm going to enjoy traveling.<br />
<br /></div>
<h3>
Would You Use This API?</h3>
<div>
When I inquired about version-to-version incompatibilities, Cisco's initial response was:</div>
<blockquote class="tr_bq">
"This definitely shouldn't be happening."</blockquote>
<div>
Followed by:</div>
<blockquote class="tr_bq">
"We are aware of the limitations resulting for not having versioned ASA REST API releases. And as of now there are no plans for us to fix this."</blockquote>
Further followed by:<br />
<blockquote class="tr_bq">
"we will update the documentation to reflect the correct behavior, once we post this fix to CCO."</blockquote>
So hey, no problem right? We might sneak <a href="http://www.google.com/search?q=REST+API+breaking+change">breaking changes</a> into the smallest of maintenance releases, but at least we'll document it! Have fun selling and supporting your application!<br />
<br />
Clearly I am one of the angry and resentful customers predicted by the articles quoted above :)</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-4698924346166937322017-03-17T03:48:00.000+00:002017-03-17T03:48:19.278+00:00Epoch Rollover: Coming Two Years Early To A Router Near You!<h2>
The 2038 Problem</h2>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://4.bp.blogspot.com/-Ar_t59l3crU/WMtSiOUCVCI/AAAAAAAAAck/yWMz4BLMfZ0ybTi3nQ3Kb95X6JETzlhPgCLcB/s1600/6941375516_e3cef824ec_k.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="150" src="https://4.bp.blogspot.com/-Ar_t59l3crU/WMtSiOUCVCI/AAAAAAAAAck/yWMz4BLMfZ0ybTi3nQ3Kb95X6JETzlhPgCLcB/s200/6941375516_e3cef824ec_k.jpg" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://www.flickr.com/photos/hooopjeellende/6941375516">Broken Time?</a> - <a href="https://twitter.com/#!/roelandvdhoorn">Roeland van der Hoorn</a></td></tr>
</tbody></table>
Many computer systems and applications keep track of time by counting the seconds from "the epoch", an arbitrary date. Epoch for UNIX-based systems is the stroke of midnight in Greenwich on 1 January 1970.<br />
<br />
Lots of application functions and system libraries keep track of the time using a 32-bit signed integer, which has a maximum value of around 2.1 billion. It's good for a bit more than 68 years worth of seconds.<br />
<br />
Things are likely to get weird 2.1 billion seconds after the epoch on January 19th, 2038.<br />
<br />
As the binary counter rolls over from 01111111111111111111111111111111 to 10000000000000000000000000000000, the sign bit gets flipped. The counter will have changed from its farthest reach after the epoch to its farthest reach <i>before</i> the epoch. time will appear to have jumped from early 2038 to late 1901.<br />
<br />
Things might even get weird within the next year (January 2018!) as systems begin encounter freshly minted CA certificates with expirations after the epoch rollover (it's common for CA certificates to last for 20 years.) These certificates may appear to have expired in late 1901, over a century prior to their creation.<br />
<br />
<h2>
NTP's 2036 Problem</h2>
NTP has a similar, but not-quite-the-same epoch problem. It keeps track of seconds in an <i>unsigned</i> 32-bit value, so it can count twice as high as the problematic UNIX counter (yay!) but NTP's epoch is set 70 years earlier: 1 January 1900 (boo!) The result is that NTP's counter will roll over about 2 years before the UNIX counter.<br />
<br />
Practically speaking, NTP's going to be fine for reasons having to do with it being primarily concerned about small offsets in relative time, and it only having to be within 68 years of correct on startup in order to sync up with an authoritative time source.<br />
<br />
<h2>
So What's Up With This Router?</h2>
<div>
Here's a weird thing I stumbled across recently. Time calculations with dates in 2036 are going wrong but they're unrelated to NTP:<br />
<br /></div>
<pre style="border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> router#<b>show crypto pki certificates test-1</b>
CA Certificate
Status: Available
Certificate Serial Number (hex): 14
Certificate Usage: Signature
Issuer:
cn=test-2
Subject:
cn=test-2
Validity Date:
start date: 02:38:26 UTC Mar 17 2017
end date: <span style="background-color: yellow;">00:00:00 UTC Jan 1 1900</span>
Associated Trustpoints: test-1
</code></pre>
<br />
But this one looks okay:<br />
<br />
<pre style="border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> router#<b>show crypto pki certificates test-2</b>
CA Certificate
Status: Available
Certificate Serial Number (hex): 12
Certificate Usage: Signature
Issuer:
cn=test-1
Subject:
cn=test-1
Validity Date:
start date: 02:37:31 UTC Mar 17 2017
end date: <span style="background-color: lime;">06:28:15 UTC Feb 7 2036</span>
Associated Trustpoints: test-2
</code></pre>
<br />
The real expiration dates of these certificates is just one second apart:<br />
<div>
<br /></div>
<div style="font-family: menlo; font-size: 11px; line-height: normal;">
<blockquote class="tr_bq">
<div style="background-color: white;">
<span style="font-variant-ligatures: no-common-ligatures;">$ <b>openssl x509 -in test-1.crt -noout -enddate</b></span></div>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="background-color: white;">notAfter=</span><span style="background-color: yellow;">Feb 7 06:28:16 2036 GMT</span></span><br />
<div style="background-color: white;">
<span style="font-variant-ligatures: no-common-ligatures;">$ <b>openssl x509 -in test-2.crt -noout -enddate</b></span></div>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="background-color: white;">notAfter=</span><span style="background-color: lime;">Feb 7 06:28:15 2036 GMT</span></span></blockquote>
</div>
So... That's unfortunate.<br />
<br />
Here's the actual certificate data and import procedure used for this experiment in case you feel inclined to test:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> crypto pki trustpoint test-1
enrollment terminal
crypto pki authenticate test-1
-----BEGIN CERTIFICATE-----
MIIBeDCCASKgAwIBAgIBFDANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQDDAZ0ZXN0
LTIwIBcNMTcwMzE3MDIzODI2WhgPMjAzNjAyMDcwNjI4MTZaMBExDzANBgNVBAMM
BnRlc3QtMjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDUjEccGNjjtv8lKNnvGpta
Z4x8LB82D2JJwTcvA5blUI2nr4vF41RqG0ifZ+Qtyqo+ntSD2QzDu3LKdSUw46if
AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBQ2NpEF0FG/g3ryNgU7Skjbm4IGHTAfBgNVHSMEGDAWgBQ2NpEF0FG/g3ry
NgU7Skjbm4IGHTANBgkqhkiG9w0BAQUFAANBAIVyT+iBimH7c/jtBrFGmKq+7YdM
eMwf9I/En/TAUqtte7QGLNRyTgBJvGgN/uc0KUjlZ5D6G/kxTwDtzse2Uow=
-----END CERTIFICATE-----
quit
crypto pki trustpoint test-2
enrollment terminal
crypto pki authenticate test-2
-----BEGIN CERTIFICATE-----
MIIBeDCCASKgAwIBAgIBEjANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQDDAZ0ZXN0
LTEwIBcNMTcwMzE3MDIzNzMxWhgPMjAzNjAyMDcwNjI4MTVaMBExDzANBgNVBAMM
BnRlc3QtMTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDUjEccGNjjtv8lKNnvGpta
Z4x8LB82D2JJwTcvA5blUI2nr4vF41RqG0ifZ+Qtyqo+ntSD2QzDu3LKdSUw46if
AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
DgQWBBQ2NpEF0FG/g3ryNgU7Skjbm4IGHTAfBgNVHSMEGDAWgBQ2NpEF0FG/g3ry
NgU7Skjbm4IGHTANBgkqhkiG9w0BAQUFAANBAIjboo8wtehMpOReLw01tW8MLYzl
rtpwYVGoHCVVpXU+s7YQtfR1pt5ZVHZ8OVeP8SoTtoS+5k97aWgBZ+hu8/M=
-----END CERTIFICATE-----
quit
</code></pre>
<br />chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-19789346009936999012017-02-01T20:28:00.002+00:002017-02-01T20:28:36.271+00:00Docker's namespaces - See them in CentOSIn the <a href="https://www.amazon.com/dp/1786461145/">Docker Networking Cookbook</a> (I got my copy directly from <a href="https://www.packtpub.com/networking-and-servers/docker-networking-cookbook">Pact Publishing</a>), <a href="https://twitter.com/blinken_lichten">Jon Langemak</a> explains why the <span style="font-family: "courier new" , "courier" , monospace;">iproute2</span> utilities can't see Docker's network namespaces: Docker creates its namespace objects in <span style="font-family: "courier new" , "courier" , monospace;">/var/run/docker/netns</span>, but <span style="font-family: "courier new" , "courier" , monospace;">iproute2</span> expects to find them in <span style="font-family: "courier new" , "courier" , monospace;">/var/run/netns</span>.<br />
<br />
Creating a symlink from <span style="font-family: "courier new" , "courier" , monospace;">/var/run/docker/netns</span> to <span style="font-family: "courier new" , "courier" , monospace;">/var/run/netns</span> is the obvious solution:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $ <b>sudo ls -l /var/run/docker/netns</b>
total 0
-r--r--r--. 1 root root 0 Feb 1 11:16 1-6ledhvw0x2
-r--r--r--. 1 root root 0 Feb 1 11:16 ingress_sbox
$ <b>sudo ip netns list</b>
$ <b>sudo ln -s /var/run/docker/netns /var/run/netns</b>
$ <b>sudo ip netns list</b>
1-6ledhvw0x2 (id: 0)
ingress_sbox (id: 1)
$
</code></pre>
<br />
But there's a problem. Look where this stuff is mounted:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $ <b>ls -l /var/run</b>
lrwxrwxrwx. 1 root root 6 Jan 26 20:22 /var/run -> ../run
$ <b>df -k /run</b>
Filesystem 1K-blocks Used Available Use% Mounted on
tmpfs 16381984 16692 16365292 1% /run
$
</code></pre>
<br />
The symlink won't survive a reboot because it lives in a memory-backed filesystem. My first instinct was to have a boot script (say <span style="font-family: "courier new" , "courier" , monospace;">/etc/rc.d/rc.local</span>) create the symlink, but there's a much better way.<br />
<br />
<span style="font-size: large;"><b>Fine, I'm starting to like <span style="font-family: "courier new" , "courier" , monospace;">systemd</span></b></span><br />
<br />
Systemd's <span style="font-family: "courier new" , "courier" , monospace;"><a href="http://tmpfiles.d/">tmpfiles.d</a></span> is a really elegant way of handling touch files, symlinks, empty directories, device nodes, pipes and whatnot which live in volatile filesystems. The feature works from these directories:<br />
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">/etc/tmpfiles.d</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">/run/tmpfiles.d</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">/usr/lib/tmpfiles.d</span></li>
</ul>
<div>
When the directives found in these directories contradict one another, the instance I've listed earlier wins. This allows an administrator to override package declarations in <span style="font-family: "courier new" , "courier" , monospace;">/usr/lib/tmpfiles.d </span>by creating an entry in <span style="font-family: "courier new" , "courier" , monospace;">/etc/tmpfiles.d</span>. Conflicts between files are resolved by the order of their appearance in a lexical sort.</div>
<div>
<br /></div>
<div>
So, what goes in these directories? Files named <span style="font-family: "courier new" , "courier" , monospace;"><whatever>.conf</span>. Each line in these files controls creation of a file / folder / symlink / etc... There are switches and options to control ownership, permissions, overwrite condition, contents, and so forth.</div>
<div>
<br /></div>
<div>
Here's the file that causes <span style="font-family: "courier new" , "courier" , monospace;">systemd</span> to create my symlink on every boot:<br />
<br /></div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> $ <b>cat /etc/tmpfiles.d/netns.conf</b>
L /run/netns - - - - ./docker/netns
</code></pre>
<br />
I'm still not <i>quite</i> ready to forgive <span style="font-family: Courier New, Courier, monospace;">systemd</span> for taking away the udev network interface naming persistency stuff and replacing it with something that's useless in virtual machines (<a href="https://github.com/systemd/systemd/commit/6c1e69f9">this</a> helps). But I'm getting there.<br />
<br />
Lately I've been really liking each new facet of <span style="font-family: Courier New, Courier, monospace;">systemd</span> as I've discovered it.<br />
<br />chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-81793577610527938702017-01-31T22:15:00.002+00:002017-01-31T22:15:17.431+00:00Anuta Networks NCX: Overcoming SkepticismAnuta Networks demonstrated their NCX network/service orchestration product at Network Field Day 14.<br />
<a href="http://fjordit.com/wp-content/uploads/2014/05/anuta_logo_simple_large32.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://fjordit.com/wp-content/uploads/2014/05/anuta_logo_simple_large32.png" height="54" width="320" /></a><br />
<a href="http://www.fragmentationneeded.net/p/gestalt-it.html">Disclaimer</a><br />
<a href="http://techfieldday.com/companies/anuta-networks/">Anuta Networks page at TechFieldDay.com with videos of their presentations</a><br />
<br />
Anuta's promise with NCX is to provide a vendor and platform agnostic network provisioning tool with a slick user interface and powerful management / provisioning features.<br />
<br />
I was skeptical, especially after seeing the impossibly long list of supported platforms.<br />
<br />
<b><span style="font-size: large;">Impossible!</span></b><br />
Network device configurations are complicated! They've got endless features, each of which is tied to others the others in unpredictable ways. Sure, seasoned network ops folks have no problem hopping around a text configuration to discover the ways in which ACLs, prefix lists, route maps, class maps, service policies, interfaces, and whatnot relate to one another... But capturing these complicated relationships in a GUI? In a vendor independent way?<br />
<br />
I left the presentation with an entirely different perspective, and a desire to try it out on a network I manage. Seriously, I have a use case for this thing. Here's why I was wrong:<br />
<br />
<span style="font-size: large;"><b>Not a general purpose UI</b></span><br />
Okay, so it's a <i>provisioning system</i>, not a general purpose UI. Setup is likely nontrivial because it requires you to consider the types of services and related configurations you deploy in your network, and then express those possibilities in a simple form. Examples of things you might choose to express are:<br />
<br />
<ul>
<li>For an MPLS PE device, are we 8021.Q tagging the traffic at the customer handoff? If so, what tag? That's a checkbox and a text field.</li>
<li>For a DMVPN router, do we want to allow direct internet access, or backhaul everything to HQ? A checkbox.</li>
<li>For various WAN interfaces, choose from a list of provider types in order to get the correct QoS templates applied</li>
</ul>
<div>
<span style="font-size: large;"><b>Pre-built Templates</b></span></div>
<div>
NCX ships with understanding of how to do lots of things (create a VLAN, configure spanning tree, define a BGP neighbor) on lots of different platforms. Much of the work is already done. We're not inventing the wheel with Ansible here.</div>
<div>
<br /></div>
<div>
<span style="font-size: large;"><b>Vendors and Features</b></span></div>
<div>
The vendor list was huge, but let's just consider a Cisco for the moment. What does it mean for Cisco platforms to be "supported" by NCX? Apparently everything in the IWAN deployment guide is supported. That's a pretty complete list of features: routing protocols, QoS, PBR, security, etc... I'm sure they don't have crazy corner case stuff (using appletalk, are you?) but that's okay because...</div>
<div>
<br /></div>
<div>
<b><span style="font-size: large;">Extensibility</span></b></div>
<div>
Need to use a feature that NCX doesn't know about? The toolkit for defining your own features, exposing them in the UI and getting them expressed as device configuration looked pretty straightforward. It boiled down to expressing a YANG model of the feature in question and then mapping that to device specific NETCONF/CLI/REST/whathaveyou configuration directives.</div>
<div>
<br /></div>
<div>
<b><span style="font-size: large;">Final Fragments</span></b></div>
<div>
<ul>
<li>Offline devices which have missed several cycles of updates do not receive that series of individual updates when they come back online. NCX somehow flattens the queued changes into a single update prior to delivering it. Frankly, this blows my mind. It suggests a surprising level intimacy with the device configuration. Imagine, for example, if one of the updates included the <span style="font-family: Courier New, Courier, monospace;"><b>bgp upgrade-cli</b></span> directive. NCX would anticipate the result and merge subsequent <span style="font-family: Courier New, Courier, monospace;"><b>address-family ipv4</b></span> directives? Maybe I misunderstood the answer to my question on this topic :)</li>
<li>NCX knows about its management path to the devices in question, and is careful not to lock itself out. I didn't get a lot of clarity about how this works, but there's no question the guys behind it are thoughtful and clever.</li>
</ul>
</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com1tag:blogger.com,1999:blog-3266263034124005485.post-53022229296287213842017-01-06T14:45:00.002+00:002017-01-06T14:45:48.978+00:00ERSPAN on ComwareThe Comware documentation doesn't spell it out clearly, but it's possible to get <a href="http://packetpushers.net/erspan-new-favorite-packet-capturing-trick/">ERSPAN</a>-like functionality by using a GRE tunnel interface as the target for a <i>local</i> port mirror session.<br />
<br />
This is very handy for quick analysis of stuff that's not L2 adjacent with an analysis station.<br />
<br />
First, create a <i>local</i> mirror session:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> mirroring-group 1 local
</code></pre>
<br />
Next configure an unused physical interface for use by tunnel interfaces:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> service-loopback group 1 type tunnel
interface <unused-interface>
port service-loopback group 1
quit
</code></pre>
<br />
Now configure a GRE tunnel interface as the destination for the mirror group:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> interface Tunnel0 mode gre
source <whatever>
destination <machine running wireshark>
mirroring-group 1 monitor-port
quit
</code></pre>
<br />
Finally, configure the source interface(s):<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> interface <interesting-source-interface-1>
mirroring-group 1 mirroring-port inbound
interface <interesting-source-interface-2>
mirroring-group 1 mirroring-port inbound
</code></pre>
<br />
Traffic from the source interfaces arrives at the analyzer with extra Ethernet/IP/GRE headers attached. Inside each GRE payload is the original frame as collected at a mirroring-group source interface. If the original traffic with extra headers attached (14+20+4 == 38 bytes) exceeds MTU, then the switch fragments the frame. Nothing gets lost and Wireshark handles it gracefully.chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com6tag:blogger.com,1999:blog-3266263034124005485.post-64054962715705392742016-11-28T16:33:00.000+00:002016-11-28T16:33:23.545+00:00ICMP Covert Channel for IOSI wrote a quick-and-dirty covert channel via ICMP for IOS routers.<br />
<br />
The channel in question isn't <i>super</i> covert. It's all in plaintext and is quite noisy because it only delivers a single byte of message payload per ping. But it gets messages from routers to the listener via pings, and that was the objective. I expect it to be useful when diagnosing IPSec issues behind unknown overload NATs.<br />
<br />
It lives <a href="https://github.com/chrismarget/ios-icmp-channel">here</a>.<br />
<br />
Invoke it on a router like this:<br />
<br />
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">Router#<b>tclsh flash:sender.tcl <target> testing 1 2 3</b></span></div>
<br />
It will then send 14 pings (13 for the characters in 'testing 1 2 3' plus an <EOM> terminator) to the target machine.<br />
<br />
The listener functions as a packet sniffer, so it requires root access. It prints out a line per incoming message, preceded by the sender's IP address:<br />
<br />
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;"># <b>/tmp/listener.py</b> </span></div>
<div style="font-family: Menlo; font-size: 11px; line-height: normal;">
<span style="font-variant-ligatures: no-common-ligatures;">192.168.5.5<span class="Apple-tab-span" style="white-space: pre;"> </span>testing 1 2 3</span></div>
<br />
<br />chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-10612290004007868572016-11-18T06:18:00.000+00:002016-11-18T06:18:20.068+00:00Inspecting SCEP enrollment traffic<a href="https://en.wikipedia.org/wiki/Simple_Certificate_Enrollment_Protocol">SCEP</a> is a protocol which facilitates client enrollment with a Certificate Authorities (CA), delivery and renewal of certificates and delegation of identity verification from a CA to a trusted Registration Authoritie (RA)<br />
<br />
A project I'm working on requires me to generate a Certificate Signing Request (CSR) on behalf client which doesn't exist yet, and deliver of those requests to the CA via an RA that I'm building. I'll then set aside the certificate and keys for installation onto the client system when it becomes available.<br />
<br />
It seemed like ripping apart a request from a real client, as delivered by a real RA would be a good place to start, so that's what I did. I set up a CA (R1), an RA (R2) and a client (R3), performed the enrollment and captured the traffic between the R2 and R1.<br />
<br />
There's a nice diagram detailing how a client delivers its to a CA on <a href="https://www.cisco.com/c/en/us/support/docs/security-vpn/public-key-infrastructure-pki/116167-technote-scep-00.html#anc6">this Cisco page</a>, so have a quick peek at the breakdown listed under <i>Client Enrollment</i> there.<br />
<br />
A CSR delivered by an RA (rather than the client) is similarly encapsulated, except that both of the PKCS7 functions are performed by the RA (with the RA's private key), rather than the client.<br />
<br />
Cisco's diagram looks fairly straightforward, but it took me a while to work out the handful of <span style="font-family: Courier New, Courier, monospace;"><b>openssl</b></span> incantations that follow.<br />
<br />
The first step was to collect the data delivered over HTTP using a sniffer. The RA's HTTP GET request looks like this:<br />
<br />
<pre style="background-position: initial initial; background-repeat: initial initial; border: 1px dashed rgb(204, 204, 204); color: black; font-family: arial; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"><span style="background-color: #f0f0f0;"> /cgi-bin/pkiclient.exe?operation=PKIOperation&message=</span><span style="background-color: yellow;">MIIJUwYJKoZI...etc...</span><span style="background-color: #f0f0f0;">
</span></code></pre>
<br />
The value of the <span style="background-color: white; color: #525252; font-family: "courier";">message</span> field is a few KB of URL encoded text, so the first step was to snag that text, stick it in a file I called <span style="font-family: "courier new" , "courier" , monospace;"><b>RA->CA.raw</b></span><br />
<br />
The text is URL encoded, so a quick substitution restored the newlines, '+', '/' and '=' characters to their usual form, leaving behind a nice base64 encoded file with 64 characters on each line. I saved it as <b style="font-family: 'Courier New', Courier, monospace;">RA->CA.b64</b><br />
<br />
Decode that base64 data to its binary form:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris$ <b>base64 --decode 'RA->CA.b64' > 'RA->CA.bin'</b>
</code></pre>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>
<span style="font-variant-ligatures: no-common-ligatures;">The result is a PKCS7 signedData blob in <a href="https://en.wikipedia.org/wiki/X.690#DER_encoding">DER</a> format. You can browse the ASN.1 info for the request I'm working on <a href="https://lapo.it/asn1js/#3082095306092A864886F70D010702A082094430820940020101310B300906052B0E03021A05003082042D06092A864886F70D010701A082041E0482041A3082041606092A864886F70D010703A0820407308204030201003182012E3082012A0201003012300D310B3009060355040313024341020101300D06092A864886F70D010101050004820100A53541D21C8FED3F189B45D60D57DDB5094557735527CCBA7B1033F8301757A70F0A3C0E5AF286AED9F68198F338E9195E9E366B9966C0785634E7764B082768C15FE646F91EB226445C1477073030B8B0B89383F83911ABEE44744D1BC8E694587609CF7D57C451FC275449EBE0E9C0FC06A60B726FE945E9F9DAFAC5A336AFDD71FAF4D9A9E508F9A17C5505055DEF5A9C042A82DAA5BFB2152B60E89757CC220AB2CCE116E908961A9A24359C39CFA71968A169F942ED03220E8E808F54D82E9A92F7F593BC371439D905624C61E87971F61AA7E8EC2FF948BDFF521ED47E11CD5AFDD4470387880A16A0E1D324984C40F7860C9C49CECE6AED449E0A6208308202CA06092A864886F70D010701301106052B0E0302070408A12E23B5DD4A3D71808202A8317EE2DF8519508A541AEA6DF68C6FF7DD78A976B367624A4BC28DD8F1D2D25B8C97D80AC1D78353CF019DE344CEB6233904D7F6BFE9CEA911359687854DEA59A49E873B438A0E83C8578E3E61A3663347188BE30A8164956985563CADDEFC9FD958102AD74F5F67156F8B58F54EB02AA320380B7A4DA436BDBC156AFCC86F296926ACDAD946365F0D72D3D0B633CD3C4174902B923EF0EE0C29E2DA22837A0D094B911D65D4225E1FC9C36E42FD77900584A63CDFB7D1092EDC47562BA0620A9CB89405BA6D8C7013A61639F1EE45E70E9CC33F8FEF558C99666662DEB115BF080277A19C5C7D67B549B74A0CE1AEF4001982D0EFD245F83284657EAD6927646B1E63E81364C2340B692892772FD13428FF7B8FA597B1C0E10A9FFC1865894B644538F6B8D4172D5ED99371CE342EB290E334C04E1E8EF57F8B7ED556E05374A0FE13A4ECC884EE4B7BB9B862412FD2F77C74D649A0854A36C737A3171CB871C35E968C3048B2BFEB2ECCE181EE2D48B001E691EE15F3EEC4E60D960602A61364E83942BC63F8B9EEDF85BBEBEE86D8A606A2DDCC1CBEE1FB34EA19445AF1F631A6AA5B0D36B4D41E302389CA8535BFDDD98DE0E41F84AEC3B551D167F2F70CA2E78F283E4CC4732F4210DFBC86B68012E68399C8096DD631FA3B548CAB34D62505298D5782C6C520C1D147B80F8B2ECE466C07836A16D74F29C2295E12A202C1950D57A01E717CBC865E6466B56539412D8E2DA43C3749DC49184D22137792151839FD47BDB25E67A1FB6A36EC1E6E4793837F28655AB959FA169D48FEE48CDCE8FB2A98BACA1C58D5609B079E6B06ED51743E95A7BB82FC04BBEBA7290719FC27468570AB5EC29415CF5C4432F4DCDF5EADC3F7096659971E9E812C0BA08C8E0DF82DC38B319C6FBFA74247DB829FE5968F2C519F26148DF127693483FC7C321812BE69DFDEA7A082031430820310308201F8A003020102020102300D06092A864886F70D0101050500300D310B3009060355040313024341301E170D3136313130383135323331395A170D3137313130383135323331395A30393111300F060355040B1308696F7363732052413124300F06092A864886F70D0109021602523230110603550405130A3432373932353635313730820122300D06092A864886F70D01010105000382010F003082010A0282010100A0AF7B30ADC81455DAE6746B1713029B44ABC24366857DE3C8AAEBE3FA9D3E18400265EB0B7ABE338926A9DFEA8F1F32E0C87AFE09877FDC82018595DF57B41EBA01112D3EDFE174A9F0E6F97D69E8FB88D40402A48D77DAD434AF8178E223E77D0C15FAA18906247B4191844F6970F12FA25AA4A77C78A3A135B45AA979BA0DD926976E5EDD517C878397C06C2CC4D698320C78514E780169B499407CA57E27ED217D872EAD4F5042E96D71779EBABC7A921BF304B89BC1D8AD08ABF02BBC580552AA0ACD9437C667EBA1449ACF63A1ABB5CA4D696B34BD388DF426849868B2A88BAB035C533C843D5374DC9EB4B1E890CBE4A7F334E607ACB68FC6AB4FE9450203010001A34F304D300B0603551D0F0404030205A0301F0603551D23041830168014FC561183248D2800D22A09D09DA14833582A0517301D0603551D0E04160414A2918C1A9CBD9495F0C75D404FB730293DB733D2300D06092A864886F70D010105050003820101008498D55447DBF60830205978E2A9211397BDF0F3053ECAED15BED736AB112AA99124F2309063D22D751844FD2BB6C9ADE7F34D12A3C5655D65D0B0A528B589FE4DFF4332ECF2FC52AFB4035DF074446CAAC06896B5F67295343DC57B5CB6520A128E0A58309CAD4BCA935E280C8F6F7BABBF5DCDE9746CCA38FD2C5C5A41FB96042CB253F615E6DF949652C67801D212C008ADACFFA2754B7B65351DD5B2A8D9CA1E2320617490C8E0B9A22A8449EB38E7935208B342B7E829DBBF45D7932922140BD6DBDA4BA9FACAB059287826C66615F773964BA49CF9B02D0E260355AF605B4024AD39F5FD92645095C544A33A07369378E410EAE60A24BFA93E2A644633318201E3308201DF0201013012300D310B3009060355040313024341020102300906052B0E03021A0500A081A73012060A6086480186F845010902310413023139301806092A864886F70D010903310B06092A864886F70D0107013020060A6086480186F84501090531120410A5CB864C8655312173680EFC59D22886302306092A864886F70D010904311604141BC25C4758447FE3A1594A682C01552F6BB5BF133030060A6086480186F845010907312213203842313141303238304630383444464433363946343238314341414334464537300D06092A864886F70D0101010500048201008A8304AAE5F65CB33FDAB2A97D8313E2EF4DF72FB2948C640DB9479903BD2012C3BCDA2F31AFA23EE582366220C7286C9FF8860A9DB6049B03DA10C36EFE843D2709303193B627C3812EB0BF23452CC4BEDFFEA260BF9C9B4FCFBD5CDAF91A921B50982B32AF38109A16BA5F4EB6C31648A35F4D608DF600FAC6150006467048CA5F8FCD2EC95DA0D2BEB7C30FBE06F12FEA09E55C82C0E186224B9F0612256DF5D16C1ABD45BFC856198E464A331C091100BE85830DE57A54A09AE7D0D629B76CB06C16EF639EC58B5F78B319B6838A9BD8417A92ECA2F905974ADFBDB1E2280E3F278A31126F4A5BDD54C67E4FA20CE0115C1F1164B526D02B13822593717D">here</a>. This blob will have the certificate of the signer included.</span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>
<span style="font-variant-ligatures: no-common-ligatures;">In a client -> CA request, the client uses his own certificate to sign re-enrollment requests, and uses a self-signed certificate to bootstrap the initial enrollment. In this case (RA -> CA), the data is signed by the RA, so it's the RA's certificate that's included. You can see it at offset 1116 in the ASN.1 parser linked in the previous paragraph.</span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>
<span style="font-variant-ligatures: no-common-ligatures;">Let's extract the RA's certificate:</span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;"></span><br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris$ <b>openssl pkcs7 -inform der -print_certs -in 'RA->CA.bin' | openssl x509 -out RA_cert.pem</b>
</code></pre>
<span style="font-variant-ligatures: no-common-ligatures;">
</span>
<br />
<div>
<span style="font-variant-ligatures: no-common-ligatures;"><span style="font-variant-ligatures: no-common-ligatures;"><br /></span></span></div>
<span style="font-variant-ligatures: no-common-ligatures;">
</span></div>
<div>
<span style="font-variant-ligatures: no-common-ligatures;">And let's have a look at it:</span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris$ <b>openssl x509 -noout -in RA_cert.pem -issuer -subject</b>
issuer= /CN=CA
subject= /OU=ioscs RA/unstructuredName=R2/serialNumber=4279256517
</code></pre>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span><span style="font-variant-ligatures: no-common-ligatures;">The message was signed by the RA and we have that certificate. The RA's certificate was signed by the CA and we <i>don't have</i> that one. We're going to need the CA's certificate in order to extract the payload of this PKCS7 signedData bundle, because without it the trust chain is incomplete so the message won't validate. The CA in this case is a </span><a href="http://www.fragmentationneeded.net/2015/03/set-up-pki-service-on-cisco-router.html">Cisco IOS router</a>. Export the certificate in PEM format:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> R1(config)# <b>crypto pki export ROOT-CA pem terminal</b>
</code></pre>
<span style="font-variant-ligatures: no-common-ligatures;"><br /></span>Save the resulting text in <span style="font-family: "courier new" , "courier" , monospace;"><b>CA_cert.pem</b></span> and validate/extract the payload from the PKCS7 signedData blob sent by the RA to the CA:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris$ <b>openssl cms -inform der -verify -CAfile CA_cert.pem -in 'RA->CA.bin' -out 'RA->CA.payload1'</b>
Verification successful
</code></pre>
<br />
Great. Now we've got the payload from the PKCS7 signedData blob. What's in there? Another PKCS7, of course. This time it's envelopedData (encrypted). <a href="https://lapo.it/asn1js/#3082041606092A864886F70D010703A0820407308204030201003182012E3082012A0201003012300D310B3009060355040313024341020101300D06092A864886F70D010101050004820100A53541D21C8FED3F189B45D60D57DDB5094557735527CCBA7B1033F8301757A70F0A3C0E5AF286AED9F68198F338E9195E9E366B9966C0785634E7764B082768C15FE646F91EB226445C1477073030B8B0B89383F83911ABEE44744D1BC8E694587609CF7D57C451FC275449EBE0E9C0FC06A60B726FE945E9F9DAFAC5A336AFDD71FAF4D9A9E508F9A17C5505055DEF5A9C042A82DAA5BFB2152B60E89757CC220AB2CCE116E908961A9A24359C39CFA71968A169F942ED03220E8E808F54D82E9A92F7F593BC371439D905624C61E87971F61AA7E8EC2FF948BDFF521ED47E11CD5AFDD4470387880A16A0E1D324984C40F7860C9C49CECE6AED449E0A6208308202CA06092A864886F70D010701301106052B0E0302070408A12E23B5DD4A3D71808202A8317EE2DF8519508A541AEA6DF68C6FF7DD78A976B367624A4BC28DD8F1D2D25B8C97D80AC1D78353CF019DE344CEB6233904D7F6BFE9CEA911359687854DEA59A49E873B438A0E83C8578E3E61A3663347188BE30A8164956985563CADDEFC9FD958102AD74F5F67156F8B58F54EB02AA320380B7A4DA436BDBC156AFCC86F296926ACDAD946365F0D72D3D0B633CD3C4174902B923EF0EE0C29E2DA22837A0D094B911D65D4225E1FC9C36E42FD77900584A63CDFB7D1092EDC47562BA0620A9CB89405BA6D8C7013A61639F1EE45E70E9CC33F8FEF558C99666662DEB115BF080277A19C5C7D67B549B74A0CE1AEF4001982D0EFD245F83284657EAD6927646B1E63E81364C2340B692892772FD13428FF7B8FA597B1C0E10A9FFC1865894B644538F6B8D4172D5ED99371CE342EB290E334C04E1E8EF57F8B7ED556E05374A0FE13A4ECC884EE4B7BB9B862412FD2F77C74D649A0854A36C737A3171CB871C35E968C3048B2BFEB2ECCE181EE2D48B001E691EE15F3EEC4E60D960602A61364E83942BC63F8B9EEDF85BBEBEE86D8A606A2DDCC1CBEE1FB34EA19445AF1F631A6AA5B0D36B4D41E302389CA8535BFDDD98DE0E41F84AEC3B551D167F2F70CA2E78F283E4CC4732F4210DFBC86B68012E68399C8096DD631FA3B548CAB34D62505298D5782C6C520C1D147B80F8B2ECE466C07836A16D74F29C2295E12A202C1950D57A01E717CBC865E6466B56539412D8E2DA43C3749DC49184D22137792151839FD47BDB25E67A1FB6A36EC1E6E4793837F28655AB959FA169D48FEE48CDCE8FB2A98BACA1C58D5609B079E6B06ED51743E95A7BB82FC04BBEBA7290719FC27468570AB5EC29415CF5C4432F4DCDF5EADC3F7096659971E9E812C0BA08C8E0DF82DC38B319C6FBFA74247DB829FE5968F2C519F26148DF127693483FC7C321812BE69DFDEA7">ASN.1 decoder</a>.<br />
<br />
This data is encrypted with the CA's public key, so only the CA (holder of the corresponding private key) can read it. We need the CA's private key. Export it from the CA:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> R1(config)# <b>crypto key export rsa CA pem terminal 3des mypassphrase</b>
</code></pre>
<br />
Save the resulting text (just the bits between the begin/end private key markers) in <span style="font-family: "courier new" , "courier" , monospace;"><b>CA_key.3des</b></span>. Strip the passphrase for sanity's sake. This is a test environment after all!<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris$ <b>openssl rsa -in CA_key.3des -out CA_key.pem -passin pass:mypassphrase</b>
</code></pre>
<br />
Now we can use the CA's private key to decode the message sent to the CA:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris$ <b>openssl</b> <b>cms -decrypt -in 'RA->CA.payload1' -inkey CA_key.pem -inform der -out 'RA->CA.payload2'</b>
</code></pre>
<br />
So... What's in this <b><span style="font-family: "courier new" , "courier" , monospace;">RA->CA.payload2</span></b> file? <a href="https://lapo.it/asn1js/#308202A23082018A02010030263124300F06092A864886F70D0109021602523330110603550405130A3432373932353635313730820122300D06092A864886F70D01010105000382010F003082010A0282010100BD915B011C74A3175F7FBA778A9D23696A054346AAE18E2B37A7390024AE7FEC7AD392143110EDBAB05067C8AE092F15BF5226DB50BBC259A175D04C3B2637B50A924DF8D8AFAA8A5A65649BFC86847247E57822F4FAD08A6FEE0FC5D5863FB8C43534C4B86AF594BC076DDB9CBF5421D4FF7A04DBA1F84B4E31378B204CFE23F2342D99FB7E10E5057029E3D6A15C572525F09E6F63D1EAC8055B3FD7F47D56D117E13E27DC02FB8EBEED1D479106285A9FBDDCBB1025D849007B3797DCD700BD810A2E80495E3374356FA3820E7477BD51DF73012F46ACC46EAA9EE130254CC1B6A1E61CF32B4A52A261496636C0D353F085834EBAEB888FCE8AE1E69C82570203010001A037301406092A864886F70D01090731071305636973636F301F060A6086480186F8450109083111040F300D300B0603551D0F0404030205A0300D06092A864886F70D010104050003820101006705C76907ADD79BA7C9B0CD259A17AF21BAC4B98D3C117BB32426140B10A0291DBCCA079B9B2AF20D2FE9B3F5100DAA341EE2BE9B9D0628C37ADAA183DBE59904591F32E6125913252FFFC19CEB269549B2D827719CD56FEED3C882B07C48715D9335967C7A7007C38CA0D65FA3AF97CCA6DE15A3F01A62ED5F001A7DB6342047DE407BF2CA19449ACD13CFE146507C16B5449CD31F12BA90E2E18DC62FAD684B506894EB8CBB6A50097ADEA961E58C50FD88E03C62F31F9BC829E21C3EDD5D64F19450A95B14E2064876BA1703248E561D18153F48E05E27CC0FD80897193FE951F74A78DAEAA8AE92866FD4F4CCCDB4EB8D96B18F1204B0F1185BF8EF86BB">Back to the ASN.1 decoder</a>... Holy cow, it's a Certificate Signing Request!<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> chris$ <b>openssl req -in 'RA->CA.payload2' -inform der -noout -subject</b>
subject=/unstructuredName=R3/serialNumber=4279256517
</code></pre>
<br />
Next steps for me are to run all of these steps backward so that I can deliver such a package to a CA for signing, but <i>without</i> having a real client or RA system. I'll start by generating keys, then a CSR, then encrypting the CSR, signing it with an RA's certificate, etc...</div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com4tag:blogger.com,1999:blog-3266263034124005485.post-6899712342493861812016-10-04T05:19:00.000+01:002016-11-18T06:20:12.952+00:00udevadm, systemd and a barcode scanner<div class="" style="clear: both; text-align: left;">
I've been fooling around with a Symbol LS2208 barcode scanner attached to a CentOS 7 machine as part of a network automation project. I learned a bit about the scanner, udev and systemd along the way.</div>
<div class="" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://3.bp.blogspot.com/-HZ_1yl1A4fw/V_MYUHWzkII/AAAAAAAAAZY/TRiCpG03ndko49Vz2tVAuUwflwZRfFG_gCLcB/s1600/wwi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="41" src="https://3.bp.blogspot.com/-HZ_1yl1A4fw/V_MYUHWzkII/AAAAAAAAAZY/TRiCpG03ndko49Vz2tVAuUwflwZRfFG_gCLcB/s400/wwi.png" width="400" /></a></div>
<div class="" style="clear: both; text-align: left;">
<b><span style="font-size: large;"><br /></span></b></div>
<div class="" style="clear: both; text-align: left;">
<b><span style="font-size: large;">The LS2208</span></b></div>
<div class="" style="clear: both; text-align: left;">
<a href="https://2.bp.blogspot.com/-7qAEwdYvbnc/V_Mn6R-1SWI/AAAAAAAAAZw/pBi7r6WnxCo7Aduk0I_P9fztkqrdiIXjACLcB/s1600/scanner.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="150" src="https://2.bp.blogspot.com/-7qAEwdYvbnc/V_Mn6R-1SWI/AAAAAAAAAZw/pBi7r6WnxCo7Aduk0I_P9fztkqrdiIXjACLcB/s200/scanner.jpg" width="200" /></a>I chose the LS2208 because there were lots of them on eBay and because documentation was available. So far I'm happy with the LS2208, but wish it didn't require a physical PC to be nearby. <strike>A <a href="http://www.vmware.com/pdf/esx_anywhereusb2.pdf">USB Anywhere</a> box may be in my future</strike> (nope, Windows only). If I'd been able to find a WiFi scanner that would POST scans directly to a REST API over TLS, I'd have gone with that instead, but it seems that <a href="http://hardwarerecs.stackexchange.com/questions/2155/barcode-scanner-that-communicates-via-restful-api">this guy</a> and I are out of luck in that regard. I've got zero interest in fooling around with WinCE or similar mobile devices with built-in scanners.</div>
<div class="separator" style="clear: both; text-align: left;">
The LS2208 gets configured <i>by scanning barcodes</i>. Special codes found in the manual. So far, the ones I've found most interesting are:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>Set Factory Defaults</li>
<li>Simple COM Port Emulation</li>
<li>Low Volume</li>
<li>Beep on <span style="font-family: "courier new" , "courier" , monospace;"><BEL></span> (still need to fool with this - seems like it could provide useful feedback to the operator)</li>
<li>Do Not Beep After Good Decode</li>
</ul>
<div>
By default the scanner appears with USB vendor/product codes 0x05e0/0x1200 which makes it emulate a USB keyboard. Fun to play with, but not how I want it to work for my project.</div>
<div>
<br /></div>
<div>
Scanning the <b>Simple COM Port Emulation</b> barcode found in the manual changes its USB personality to 0x05e0/0x0600, so that it shows up as an <span style="font-family: "courier new" , "courier" , monospace;">hidraw</span> Linux device. I can't find any indication that it's a serial port, though the <span style="font-family: "courier new" , "courier" , monospace;">symbolserial</span> device driver loads in CentOS 7.</div>
<div>
<br /></div>
<div>
With each scan, the device at /dev/hidrawX produces 64 bytes consisting of:</div>
<div>
<ul>
<li>A single byte indicating the length of the scanned data. UPC codes, for example, are 12 bytes long so they always produce 0x0C as the first byte.</li>
<li>The scanned data</li>
<li>Padding with <span style="font-family: "courier new" , "courier" , monospace;"><NUL</span>> characters up to 64 bytes in total</li>
</ul>
<div>
We can take a quick look at the scan data with: <span style="font-family: "courier new" , "courier" , monospace;"><b>od -t x1 < /dev/hidraw0</b></span>.</div>
</div>
<div>
<br /></div>
<div>
<span style="font-size: large;"><b>A tiny bit of python</b></span></div>
<div>
This little program reads from the scanner and spits out the result:</div>
<div>
<br /></div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> #!/usr/bin/env python
import argparse
import sys
defaultDevice = '/dev/scanner'
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--dev', dest='d', default=defaultDevice,
help='Scanner device; defaults to '+defaultDevice)
parser.add_argument('-o', '--out', dest='o', help='Output file')
args = parser.parse_args()
inDev = open(args.d, 'rb')
inDev.flush()
if args.o:
outFile = open(args.o, 'a')
else:
outFile = sys.stdout
while True:
inBytes = inDev.read(64)
length = ord(inBytes[:1])
value = inBytes[1:length+1]
outFile.write(str(length)+"\t"+value+"\n")
outFile.flush()
</code></pre>
<div>
<br /></div>
<div>
<b><span style="font-size: large;">udev</span></b></div>
<div>
Not wanting to count on the scanner always landing on <span style="font-family: "courier new" , "courier" , monospace;">/dev/hidraw0</span>, the next task was to write a udev rule to make it easy to find. I wound up with the following in <span style="font-family: "courier new" , "courier" , monospace;">/etc/udev/rules.d/10-scanner.rules:</span><br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> KERNEL=="hidraw[0-9]*", ATTRS{idVendor}=="05e0", ATTRS{idProduct}=="0600", GROUP="barcode", ACTION=="add", SYMLINK="scanner", TAG+="systemd", ENV{SYSTEMD_WANTS}="BarcodeScanner@%N.service"
</code></pre>
<br />
Essentially, I'm matching <span style="font-family: "courier new" , "courier" , monospace;">hidraw</span> devices with the appropriate vendor and product codes, setting the resulting device file to be owned by group <span style="font-family: "courier new" , "courier" , monospace;">barcode</span> (a group I created for use by the scanner project) and creating a symlink: <span style="font-family: "courier new" , "courier" , monospace;">/dev/scanner -> /dev/hidraw0</span><br />
<br />
When the device appears, <span style="font-family: "courier new" , "courier" , monospace;">udev</span> will ask <span style="font-family: "courier new" , "courier" , monospace;">systemd</span> will kick off the BarcodeScanner unit with an argument (%N in the udev rule) indicating the path to the scanner device.<br />
<br />
<b><span style="font-size: large;">systemd</span></b><br />
Finally, we need the <span style="font-family: "courier new" , "courier" , monospace;">systemd</span> unit file to go with that udev rule. Here's my <span style="font-family: "courier new" , "courier" , monospace;">/etc/systemd/system/BarcodeScanner@.service</span> unit file:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> [Unit]
Description=Simple Symbol Scanner
StopWhenUnneeded=yes
[Service]
Type=simple
ExecStart=/tmp/scan.py -d %I -o /tmp/scanned.txt
[Install]
WantedBy=multi-user.target
</code></pre>
<br />
The <span style="font-family: "courier new" , "courier" , monospace;">StopWhenUnneeded</span> directive causes <span style="font-family: "courier new" , "courier" , monospace;">systemd</span> to kill (SIGTERM, then SIGKILL if needed) the <span style="font-family: "courier new" , "courier" , monospace;">scan.py</span> loop when nothing "wants" it. The %I evaluates to the device file passed in by <span style="font-family: "courier new" , "courier" , monospace;">udev</span>.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">Type=simple</span> tells <span style="font-family: "courier new" , "courier" , monospace;">systemd</span> that it shouldn't expect this unit to properly <a href="https://linux.die.net/man/1/daemonize">daemonize</a> itself.<br />
<br />
Poke <span style="font-family: "courier new" , "courier" , monospace;">systemd</span> so that it notices the new unit file:<br />
<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> sudo systemctl daemon-reload
</code></pre>
<br />
Now, when the scanner's USB cable is plugged in, the python code starts up and gets pointed (-d argument) at the scanner to start logging bar codes to /tmp/scanned.txt. When the scanner is unplugged, the BarcodeScanner unit is no longer "wanted" by anything, so <span style="font-family: "courier new" , "courier" , monospace;">systemd</span> kills it off.<br />
<br /></div>
chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com3tag:blogger.com,1999:blog-3266263034124005485.post-36676121314747861142016-09-21T15:29:00.001+01:002016-09-21T15:29:53.041+01:00Cisco Debug Persists Through RebootNormal boot time messages from a C881 router look something like this:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> System Bootstrap, Version 15.4(1r)T, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 2013 by cisco Systems, Inc.
Total memory size = 1024 MB
C881-K9 platform with 1048576 Kbytes of main memory
Main memory is configured to 32 bit mode
Readonly ROMMON initialized
IOS Image Load Test
___________________
Digitally Signed Production Software
Self decompressing the image : ###<snip>### [OK]
</code></pre>
<br />
But there's one router in the fleet which does this instead:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> System Bootstrap, Version 15.4(1r)T, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 2013 by cisco Systems, Inc.
Total memory size = 1024 MB
C881-K9 platform with 1048576 Kbytes of main memory
Main memory is configured to 32 bit mode
Readonly ROMMON initialized
Using monlib version 2
Using version info 2
dfs_openfile: Opening file.....
dfs_openfile: Opened file / with fib = 4019e5c
Reading cluster = 126, offset = 0, nsecs = 8
Reading cluster = 133, offset = 0, nsecs = 8
Reading cluster = 17013, offset = 0, nsecs = 8
Reading cluster = 17458, offset = 0, nsecs = 8
Reading cluster = 18056, offset = 0, nsecs = 8
Reading cluster = 17053, offset = 0, nsecs = 8
dfs_closefile: Closing file.... 4019e5c
dfs_closehandle: Closed file.... 4019e5cUsing monlib version 2
Using version info 2
dfs_openfile: Opening file....c800-universalk9-mz.SPA.154-3.M4.bin
dfs_closefile: Closing file.... 4019e5c
dfs_closehandle: Closed file.... 4019e5c
dfs_openfile: Opened file /c800-universalk9-mz.SPA.154-3.M4.bin with fib = 4019e5c
Reading cluster = 17053, offset = 0, nsecs = 8
Reading cluster = 17053, offset = 0, nsecs = 128
Reading cluster = 17069, offset = 0, nsecs = 128
Reading cluster = 17085, offset = 0, nsecs = 128
<--- ~1300 lines removed --->
Reading cluster = 58703, offset = 0, nsecs = 128
Reading cluster = 58719, offset = 0, nsecs = 80
IOS Image Load Test
___________________
Digitally Signed Production Software
Self decompressing the image : ###<snip>### [OK]
</code></pre>
<br />
Um. Okay. What's going on here?<br />
<br />
It turns out that there are a couple of funny things about debugging filesystem operations:<br />
<ol>
<li>You can't see that it's turned on from within IOS:</li>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;">C881#<b>debug filesystem flash:</b>
C881#<b>show debugging</b>
C881#
</code></pre>
<br />
<li>The setting persists across both reboots and power interruptions. Apparently this directive sets a hardware flag somewhere. <code style="color: black; word-wrap: normal;"><b>no debug filesystem flash:</b></code> made those messages go away.
</li>
</ol>
<div>
The setting probably applies to any storage device available from within the ROMMON:</div>
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> rommon 1 > <b>dev</b>
Devices in device table:
id name
flash: compact flash
bootflash: boot flash
usbflash0: usbflash0
</code></pre>
<br />
This was new to me.chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-79790633404591595072016-09-17T05:45:00.001+01:002016-09-17T05:46:32.215+01:00Let's Encrypt plugin for ASAI wrote a <a href="https://certbot.eff.org/">certbot</a> (Let's Encrypt ACME client) plugin for Cisco ASA. It runs on a separate box, talks ACME to the Let's Encrypt service and uses the ASA REST API to manage certificates on the ASA.<br />
<br />
<b><a href="https://github.com/chrismarget/certbot-asa">Details here</a>.</b><br />
<br />
If you try it out, please let me know how it goes?chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0tag:blogger.com,1999:blog-3266263034124005485.post-6767240194520074412016-07-26T21:58:00.002+01:002016-07-26T22:23:24.677+01:00Bailed out by Comware's python interpreterSomething funny happened to an IRF stack the other day. The gear was moved to a remote location and, as part of the move, the cables/transceivers were moved around.<br />
<br />
The IRF (10Gb/s) and uplink (1Gb/s) ports switched places.<br />
<br />
The new IRF ports (5 and 6) got added to the configuration just fine, leaving me with:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> #
irf-port 1/1
port group interface Ten-GigabitEthernet1/1/1
port group interface Ten-GigabitEthernet1/1/2
port group interface Ten-GigabitEthernet1/1/5
port group interface Ten-GigabitEthernet1/1/6
#
irf-port 2/2
port group interface Ten-GigabitEthernet2/1/1
port group interface Ten-GigabitEthernet2/1/2
port group interface Ten-GigabitEthernet2/1/5
port group interface Ten-GigabitEthernet2/1/6
#
</code></pre>
<br />
But IRF would't release the old ports making it impossible to repurpose them as uplinks:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> [switch]<b>irf-port 1/1</b>
[switch-irf-port1/1]<b>undo port group interface Ten-GigabitEthernet1/1/1</b>
Check failed for reason:
Can't support IRF on a port with 1000M speed!
[switch]
</code></pre>
<br />
Can't remove a port from the IRF group because it's ineligible to participate in IRF. Okaaaaay...<br />
<br />
Without functioning uplinks, it was impossible to transfer the saved configuration away for an off-box edit.<br />
<br />
<b><span style="font-size: large;">Python to the rescue!</span></b><br />
I split the IRF, used python to edit the stored configuration in-place on each IRF member, then rebooted the switches individually. Here's the edit-by-python:<br />
<pre style="background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: "arial"; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;"><code style="color: black; word-wrap: normal;"> <switch><b>python</b>
Python 2.7.3 (default, Apr 10 2014, 16:32:11)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> <b>import fileinput, re, sys</b>
>>> <b>for line in fileinput.input('flash:/startup.cfg', inplace = True):</b>
... <b>if not re.search(r' port group interface Ten-GigabitEthernet[12]/1/[12]'
,line):</b>
... <b>sys.stdout.write(line)</b>
...
>>> <b>^D</b>
<switch>
</code></pre>
<br />
Many thanks to my pal <a href="https://twitter.com/netmanchris">Chris Young</a> for both pointing out that I had a python interpreter at my disposal, and suggesting that I use it to butcher the saved configuration.chris margethttp://www.blogger.com/profile/06646973209424821070noreply@blogger.com0