Kestrel has additional options, as well as a breaking change if you are using SSL with Kestrel. Review the changes in Kestrel as well as the changes in how to run SSL with Kestrel. Plus, learn how to use SSL in Docker.
- [Instructor] There are several changes to Kestrel in ASP.NET Core 2.0 and most of them are aimed at making it more suitable as an internet-facing server. There's server limits for max client connections, request body size, and request body data rate, but there's also a breaking change if you are using IIS with Kestrel. It's probably not that big of a deal because in production, you would be using SSL with IIS or Apache or whatever your true web server is, but if you're using SSL with Kestrel as I showed you in the last chapter, you can no longer configure Kestrel for HTTPS the way you used to, and I will show you how to do it differently now.
The start of the process is the same. You creature your PFX file, copy it to the project, but instead of creating an X.509 certificate, you add Listen options to the UseKestrel() command and that's where you configure the ports for HTTP and HTTPS. And then remember we have to change the SSLPort within MVC if we're not using 443, the default, so that the routing works correctly with the required HTTPS attribute.
So, let's look at this in code and see how it all works. So, we need to set the SSL port in two different places, so I find it convenient to set the SSL port in the launchSettings.json 'cause then we can access it through the configuration system and not have to remember to keep changing it. So, if we go into Program, we have another helper method that I created in the extension methods called UseKestrelWithHttps().
And if we go into that definition, we set up some variables up here, the SSL port and the regular port. We update the configuration to include the launchSettings.json file, and this is the same thing we did in 1.1. We build the configuration so we can access it and then we get the SSL port and we get the regular port. Now, here is the change, is that in UseKestrel, we can't just create a 509 certificate and say use HTTPS.
We have to add Listen to the options and we want to set up both the regular port, which is not using HTTPS, as well as set up the SSL port. And to do that, we set the listenOptions to use HTTPS and then we get the key file and pass that in. Now, it's important that you use Path.Combine on this, as well as the current directory because the path structure is different between Windows and Unix.
So, the last parameter to pass in is the password and I've got that here as a constant. If you were to do this, you'd have to change it to your own PFX file name and make sure you update the correct password. So, that configures Kestrel and remember, the port that we're using is 44300, so MVC needs to know that we're using a different port. So in Startup, we can configure that the same way we configured Kestrel by getting the value of the SSL port out of the launchSettings.json file and then setting the SSL port here on line 62 to that value so that the routing engine knows how to properly route to HTTPS.
So, we'll switch this back to Kestrel and note, I am not running in Docker. I have my ASP.NET Core application as the Startup project. When we get into Docker, we have to change things just a little bit again. So, let's run this and confirm that it works. I have Docker containers running that are already using port 443. So, this is something probably important for you guys to see and what we want to do here is if you're not familiar with Docker, we use docker ps, which shows us the names of everything and then we can do docker kill and we have to pass in enough of the container ID to be unique.
Let's put in 9756e, and that kills the first one. And then let's kill d5db. And now, when we do docker ps, we should have nothing running, which frees up our 44300 port. There's one downside of hard coding ports into your application. Visual Studio is really good at randomly selecting ports.
So, let's just confirm again. I've got my UseNoServerBuildOptions and go ahead using compression and caching 'cause it does make a difference. I've got my UseKestrelWithHttps() helper method. UseIISIntegration(). UseStartup and Build. So, let's try this again. Here we have our application running on 55057, which in our launchSettings is the Kestrel port. We go to Log in, it's going to redirect us to HTTPS.
We get the warning that it's not secure. And here, it confirms that we are trying to redirect to HTTPS and port 44300. So again, just to recap, using HTTPS with Kestrel, we have to configure Kestrel to listen and we want to include both the non-secure, as well as the secure port. We have to then pass our key into the UseHttps method of the listenOptions, not of the Kestrel options, and we want to make sure that we configure MVC to use the proper SSL port.
So, a slight change from earlier versions of ASP.NET Core but still very workable. So now, let's move on to how would you use SSL with Kestrel in Docker 'cause there's some additional considerations that we want to cover. Using SSL in Docker has a little twist on what we needed to do with straight up using SSL in Kestrel. So first and foremost, you have to enable SSL in Kestrel, map the entry ports to 80 and 443 in docker-compose, so we've already done this.
8080 maps to 80, and 44300 maps to 443. This is the part that's a little counterintuitive. We actually need to set the SSL port in MVC to the Docker Port of 44300, and that is because of how routing is working. It won't redirect to the correct port if we don't specify that it's different. And then we set the service URL in docker-compose project, which I've already shown you that I have set to 8080.
So, let's walk through this in code to make sure that we're clear on all the nitty-gritty details. So, I have a different helper method called UseKestrelWithHttpsForDocker, kind of a long name, I get it. So, here we have UseKestrel and I'm listening on port 80 and on 443, still adding in my certificate and password. Notice that I am just using 80 and 443.
I'm not using the ports from the launchSettings.json. So then in Startup, you would think that all we need to do is say services.AddMvc and it would work because we're using 80 and 443. However, when you route to a secure port in your browser, if you don't specify an SSL Port in MVC, it will then not specify the Docker port that we need, which to me is a little counterintuitive, but hey, it's the way of the world.
So, let's go in and add these lines back in. I still have 44300 set up in my launchSettings. And even though Docker ignores that, we can still use that as a convenient mechanism to store port number. So now, I'm going to switch back to docker-compose as the startup project. I'm going to confirm that 8080 is indeed my service port, and it is 'cause we start the application non-SSL.
And we run this in Docker and it will launch up on localhost:8080, which maps to 80 inside of the container. And then when we click on that secure link, it's going to reroute our local browser to the SSL port of MVC, so we're on 8080 right now. I click Log in, which has to require HTTPS attribute and I forgot a detail, so let's go back in and let me just show you what I mean.
If I were to go :44300 right here, it would redirect us perfectly fine. So, what I've demonstrated is one of the downsides of overcomplicating the startup process by having all these different methods and Microsoft's a great step to simplify the configuration and logging process. In my example code here, does just the opposite 'cause I'm trying to show so many different things, but what I forgot to do is actually add the launchSettings.json into the configuration, so when line 61 executed, it just returned a zero.
Fortunately, it's a very simple fix. I can go into my extension methods here and I have this method UseLaunchSettingsConfig and I can go up to my UseKestrelWithHttpsForDocker and I've got my builder right there. I just simply add UseLaunchSettingsConfig() and I rerun this. And let's just, to be safe, put a break point right here on line 62.
And I run the code, build the container, executes, gets here, we have an SSL port. Now, 4300, that's a winner. Let's continue on, and our app has loaded up again. Again, pointing at 8080. Let me close the failed browser. And then when we click Log in, that will redirect us to 44300 as we expect. Again, running on port 443 inside the container.
So, just to be clear because I find this a little bit confusing. If you get it right off the bat, then that is fantastic, but when you're running with Kestrel in SSL in Docker, you map 8080 to 80 or any port to 80. 44300, again, any port to 443. Your application inside is running port 80 for HTTP requests, port 443 for HTTPS as the standard port, but we still have to tell MVC that the SSL port is 44300 and that is just a quirk of the way everything works.
So anyway, not that you will probably be running in SSL in Kestrel in Docker, but I wanted to make sure that if that was something you wanted to test that you understood how to do it. And so, there you go.
- Running and debugging ASP.NET Core applications
- Pros and cons of migrating existing applications to ASP.NET Core.
- Built-in dependency injection
- Environment awareness and app configuration
- Web host configuration and SSL
- View components invoked as tag helpers
- Configuration and logging
- Using Razor Pages