 to introduce Carl to the stage. He's a researcher up at UW. He's been a friend of ours for a long time, spoken at a couple of tour cons. So please welcome him to the tour con stage. All right, thank you. So today I'm going to talk about a third party service I built called TLS My Net, which allows you to enable HTTPS for home network devices through the standard Let's Encrypt service. And this might sound to you like a pretty uninteresting talk. It's like, OK, it's how you use Let's Encrypt, blah, blah, blah. But there's actually a bunch of issues, in particular with local network devices, that make it hard to use and also reasons why you might want to use HTTPS or TLS on your home network. So a question that I get, let's see, let me start this here. So a question that I get commonly asked is, all right, so why do you need TLS on your home network? You already have WPA2 on your wireless network. Isn't that enough encryption for you? So it turns out that browsers are starting to require TLS for what they consider powerful APIs. And so this can mean using things like requesting permission to access the camera or the microphone or using certain permissions or capabilities that you would not want a compromised website to be able to have. And so you might want to build a web app that uses these powerful APIs, but you might also want them to talk to local network devices. And the problem is that you can't make cross-origin requests from insecure sites to HTTPS sites to HTTP sites. And so you really can't make these web apps that or these secure web apps that talk to local devices. And in particular, the issue that came up for me, which caused me to think about this whole thing, I was writing an app for a Chromecast that would talk to a local network tuner on your network and then show a current over-the-air channel on your Chromecast. So Chromecast requires its applications to be delivered over HTTPS. The HD Home Run tuner in particular does not support HTTPS. And so in fact, this is impossible to build currently. And so I was trying to figure out, why doesn't it support HTTPS? How can we get them to support HTTPS? And it turns out that there is a lot of issues for enabling TLS on local devices. So the first one is that these local devices are often discovered by IP. So in the HD Home Run case, the HD Home Run device actually connects out to their cloud service and says, hey, this is my local device. When you want to find a HD Home Run device, you connect out to the same cloud service. And since you're knotted through the same IP, it can say what the local IP addresses are of the devices on the same sort of knotted external IPs. And so you can discover internal devices that way. There's a bunch of other different ways of discovering local devices by IP address. But in general, you only have an IP address and not a host name. And certificates are generally issued for host names right now. And they're certainly not going to be issued for internal IP addresses. So you might propose solving the solution by just issuing a certificate that is common across all devices. So let's say all these tuners have one common certificate and you connect to that. Unfortunately, this is easily abused. So you might remember the Superfish Fiasco from several years ago on Lenovo laptops, where basically there was one static public-private key pair that was shipped. And once you have the private key, then you can impersonate the service or the cert to any other device that trusts that public key. And similarly, even if you were to create a unique cert for each device, some manufacturers like to use a constant host name for each device. So you might have like routerlogin.com, for example. And each device might have its own certificate for routerlogin.com. And the problem there is that if you have one device for routerlogin.com, then you can impersonate routerlogin on a different network with a different device. And one of the issues of using let's encrypt to solve this by automatically creating these certificates locally is that end users typically don't have their own domain name. And even if they do, these local devices usually aren't externally facing or they're not passed forwarded through the NAT. So standard tools like let's encrypt and the standard cert bot doesn't really work for creating the certificates for these devices. But it turns out that there is one company that has actually solved this issue. And that company is Plex. And so here's how Plex has solved it. And by the way, if you're not familiar with Plex, Plex is basically your own private Netflix. So you set up your own Plex server. You load your own media onto it. And then you can give access to it to your friends. They can access it remotely over the internet and locally on your network. And it's all secured by HTTPS and TLS. And they've basically figured this out and made it work. So here's how they did that. Each server has a 16-byte GUID. And they issue a wild card certificate to your server for that GUID.Plex.Direct. And then when you want to connect to a Plex server by IP address, you go to that IP address dot the server GUID.Plex.Direct. And then in the background, they have a DNS server that resolves that IP address GUID.Plex.Direct to just that IP address. And this allows for dynamic IP addresses, both exposed through nets onto the internet and also for local IPs. So it'd be nice to use Plex's solution just off the shelf as it is. Unfortunately, the way that they actually implemented this is they partnered with a certificate authority to issue these certificates. I believe they ended up actually paying some money to this certificate authority to make this work. And most IoT vendors aren't going to spend any amount of money to increase security whatsoever. And so I thought, well, hmm, can we sort of emulate this with Let's Encrypt? And well, this is what that talk is about. So before I get into the details about how we make this work, I'll quickly mention how Let's Encrypt issues certificates. It uses this protocol called the Automated Certificate Management Environment called ACME protocol. And this is implemented by SIRTBOT and their CA site software called Boulder, along with some third party clients as well. And it basically does automated domain validation. So these are only domain validated certificates. And the way that this works is that the CA issues challenges to prove that you have control over the domain that you claim you have control over. And so there's two main challenges that are used right now. There are some that used to exist and some that are coming later. But the main two challenges right now are HTTP01, which is please create a file at this specific URL with specific contents. And the second one is please add a text record with specific contents onto this domain. And the DNS01 challenge is the only way that you can actually get wildcard certificates. So Let's Encrypt has this idea of accounts. And accounts are basically tied to a public-private key pair. And the public key is essentially your account ID. Now for performance reasons, they actually have an integer account ID. But basically you can go from a public key to your account ID. And then if you want to renew your certificate or do anything else with your account, basically you just re-sign these requests with your public key saying, hey, that account that I registered with the key that I created before, I'm the same person. So let me please do this again. So the solution that I'm proposing here is a service called TLSMyNet, which lets you issue wildcard search for subdomains where the subdomain name is tie tier Let's Encount public key. And so tying the account or the subdomain name to your account key lets you verify the legitimacy of the certificate at an application level. We can't guarantee that, say, if you go to any TLSMyNet site that it will be your server that you're talking to. But if you go to your certificate or public key fingerprint.tlsmy.net, then you are talking to one of your machines. And so the way that we're going to use this is we're going to use a Let's Encrypt and SIRP bot as normal. But we're going to prove ownership of the private key of your Let's Encrypt account to a third party domain for subdomain validation through a text record. And this is what TLSMyNet does. So the way that this works is a device initiates a subdomain wildcard certificate request to Let's Encrypt through SIRP bot. The device sends this challenge request. And then so when it contacts Let's Encrypt, Let's Encrypt responds back with a challenge to say, please prove ownership of this or control of this subdomain. So then the device sends this challenge request back to TLSMyNet. And this request is signed with the same Let's Encrypt private key using JWS. And the thumbprint of the public or the corresponding public key is used as the subdomain of TLSMyNet, My.NET. So you can't actually request SIRPs for a different account. And the way that this works is it's just a base 36 encoding of a SHA-256 hash of a particular way of hashing public keys. And so there are a couple of ways. So the way that this ends up being implemented is with a couple of Python scripts. So there's dnserver.py, which resolves a.b.c.d. thumbprint.tlsmy.net to a.b.c.d. And this allows you to basically use a host name instead of an IP address. And because it's a wildcard certificate, the TLS stack will accept that as a match and say that the certificate works. The second thing that it does is it provides these text records for subdomain verification. So when you send a challenge to us, we will add a text record for thumbprint.tlsmy.net so that we can get a wildcard for that. And the way that you submit these requests or these challenge requests to us is through this web server, which is just another Python script, which handles these requests for creating these text records. It's implemented with async.io, aio.hdtp, and JW crypto modules. And we also have a Redis server that sort of connects the two scripts together. So when we receive a valid request through the web server, we create a temporary text record in this Redis store that the DNS server can then access. And the nice thing about this is that this can be completely stateless. Because you are proving control over a particular public key by proving knowledge of the corresponding private key, we don't actually have to create any accounts for you. We just know that you have control over the subdomain that corresponds to the hash of your let's encrypt account ID. And so basically we don't have to do any long-term state storage. So it makes a very lightweight to run. On the client side, there are two more Python scripts. So one is called GetDomain, which basically just looks at your let's encrypt config files and comes up with a particular domain name that you will use or that you will request. And then there's also a RetrieveChallenge Python script, which is designed specifically to work with certbot as a manual authentication hook. And it communicates through environment variables that receives the domain that you want to authenticate for. It receives the challenge token that let's encrypt gives you that you need to add it as the text record. And then it takes those and uses your let's encrypt account private key to sign those and send that off to TLS Minet. And I don't see anyone out with their laptops. I'll say you can follow along with if you want, but it's probably too late. But if you want to try this later, you can just go to tlsmi.net. And that will redirect you to my GitHub repo. Just read the instructions and then read me. And it's basically as simple as this. So you set up this environment by basically cloning my repo and setting up a local directory for your let's encrypt account information. So you don't have to be root or anything. You'll create a let's encrypt and count yourself. So it will automatically generate this public private key locally and store it in your home directory. There is you need to tell these scripts what account private key you want to use to sign all of these challenges. And assuming you only have one account, you can just use this simple shell script one liner to say, hey, just give me the first private key file that you find in this let's encrypt home directory. And then you run certbot with this mess here, which basically says use the let's encrypt configuration in my home directory. I want to only request a certificate, not reconfigure the server or do anything. I want to do it manually, but the way that I want to do it manually is to use this manual authentication hook script and then the domain I'm going to get from another Python script. And so I did this on the plane last night, and it still works, so hooray for that. So if all works well, you should get your new certificates in some files in your home directory and dot let's encrypt slash live slash your thumbprint.tlsmy.net. So then you can take those certificate and your private key files, and you can copy those to your home network devices. And then basically you're done. Now they're only valid for 90 days, so don't forget to update those every 90 days or so. So briefly, I'm going to talk about the risk model here because you might be thinking, well, this guy up here can now impersonate anything, and that is true. So basically the third party domain service, tlsmy.net in this particular example is assumed to be trusted because they can always issue certs for your subdomain. But sort of the way that I envision this going forward in several instances is that sort of each device manufacturer might have their own domain that they use for this, and you sort of trust that manufacturer anyway, so maybe you should trust them. I don't know. But even if you don't, there's this cool feature called a certificate transparency where you can search these certificate transparency logs to ensure that no certs have been issued for your subdomain that you weren't aware of. So for example, this is my home network subdomain here. I searched for it on crt.sh, and it shows that it's been issued twice once in September and once on the plane last night. And then you can go in there and see if it's been revoked. And further down, you can check that the public key matches what you expect it to be and that the hash matches and everything is good and kosher. So right now, tlsmy.net is sort of a public service. It's not getting a whole lot of use at the moment. It's currently limited to 50 certificates per week because Let's Encrypt assumes that I have control over the whole tlsmy.net domain. So if I'm getting all of these certificates, why don't I just get a wildcard certificate for the whole thing? However, I've engaged them on the forums and they said, yes, this is actually a legitimate use of Let's Encrypt. And so if usage gets up to the point where rate limits become an issue, we can probably whitelist that or add you to the public suffix list or things like that. Ultimately, I would like to see Let's Encrypt do some sort of version of this natively. And maybe this will prod them into that sort of direction. But for now, I sort of see this as a proof concept service to encourage tlsadoption. And it makes it really easy. So please bug your IoT vendors to support tls because it's becoming increasingly important to support. So in summary, going forward, tlsupport is essential for all of these innovative web applications. But there are a bunch of problems that make getting tls certificates for local network devices difficult. But I have presented a proposal for a service where we can easily enable tls on these devices using Wellcard certs and Let's Encrypt and this third party service. So with that, I thank you for your attention. And I will take questions out on the beer garden. Oh, and it's lunch. So yeah, it's lunch, everybody. Be back here at 2 o'clock for Pookie Bear's talk, Real Life DevSecOps. You can also go outside and grab some food truck, or you should have some time to go to the mainland and get some food.