Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for HTTPS #227

Open
mu88 opened this issue Mar 7, 2019 · 19 comments
Open

Add support for HTTPS #227

mu88 opened this issue Mar 7, 2019 · 19 comments

Comments

@mu88
Copy link

mu88 commented Mar 7, 2019

Right now, BaGet is always running under http://localhost:5000. It would be great to have a switch in appsettings.json to run under HTTPS.

@WernerMairl
Copy link
Contributor

BaGet is working fine with https - depending on the hosting area.
(Azure WebApp/Kudu, Docker Environment...)

Appsettings.json is only the development default, you can/should define your requirements on runtime!

Yes, there are options to implement https inside Kestrel, but in my experience typically this the "part of the job" that should be implemented by the hosting environment and not inside BaGet.

If you provide more information what you try to do, we may be able to help you in some way...

Werner

@mu88
Copy link
Author

mu88 commented Mar 8, 2019

In most of the cases, I agree with you, Werner. However, for internal purposes, I don't need a full-fledged web server. I want a simple 'download and run' NuGet server without the need to setup all the other stuff. That's what I love about BaGet!

@loic-sharma
Copy link
Owner

I personally use the same approach that @WernerMairl describes and this works well for production workloads. That being said I completely agree with @mu88, BaGet should work well as a standalone app. I'll go ahead and a config for this, thanks for the suggestion! :)

mu88 pushed a commit to mu88/BaGet that referenced this issue Mar 10, 2019
Allows to use Kestrel with HTTPS even without a Reverse Proxy (e. g. for development or internal purposes).

Addresses loic-sharma#227

See NuGet/NuGetGallery#227
@cabal95
Copy link

cabal95 commented May 17, 2019

@WernerMairl Can you explain how to make SSL work, since you mention that it already works? My environment is a Linux server with BaGet running in a docker container. In order to get SSL I have to use a reverse proxy that handles the SSL itself. However, BaGet builds absolute URLS based solely on the request URL (which means it becomes localhost:5555) so the /v3/index.json response comes back with nothing but localhost:5555 URLs, which obviously causes package submission to fail. There doesn't seem to be a way to override the hostname/port used.

@hypervtechnics
Copy link

@cabal95 As far as I can see the Urls generated by BaGet take there information from the Forward headers. Did you set them correctly. Also there is the PathBase setting if you are running in subdirectory.

@cabal95
Copy link

cabal95 commented May 24, 2019

Yes, it is. I just verified with a tcpdump trace that Apache is sending along the X-Forwarded- headers. I'm just using Apache's standard reverse proxy config:

	<Location />
		ProxyPass http://localhost:5555/
		ProxyPassReverse http://localhost:5555/
	</Location>

However, it is partially working now. Yesterday I found and added the ProxyPreserveHost On option (which from the docs means Apache sends the original Hostname requested instead of the "new" hostname) and that seemed to fix it from sending back localhost instead of the proper hostname.

The /v3/index.json is still sending back just http:// URLs instead of https:// which isn't great, because when I upload a new package it will still send my API key unencrypted (and then Apache will redirect it to SSL), but at least it is functional now.

When I looked at the BaGet source code, it seems to be building the URLs solely based on the Request Scheme & Hostname and not looking for any X-Forwarded- headers like it would need to.

@hypervtechnics
Copy link

Probably relevant lines are:

options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;

and
app.UseForwardedHeaders();

They may or may not be relevant - I am not yet that familiar with the codes structure/architecture.

@cabal95
Copy link

cabal95 commented May 26, 2019

Aha. Okay, based on this I was able to determine that it is honoring the X-Forwarded-Proto header - but Apache does not send it by default. When I modified the Apache config to send that header, then the URLs were indeed built with https://. However, the X-Forwarded-Host header is still ignored. Looking at the documentation for that ForwardedHeaders enum, it appears that the above code needs to be modified to also include the ForwardedHeaders.XForwardedHost bit in the mask. That is probably why it is being ignored.

@kcsudeep
Copy link

kcsudeep commented Dec 3, 2019

Hi @cabal95,

I am having similar issue where /v3/index.json is sending back http instead of https. You mentioned you changed apache config to get https back. Can you please let me know what change you had to make ?

@cabal95
Copy link

cabal95 commented Dec 3, 2019

This is what I ended up using to get it to pass through everything I needed.

Obviously this isn't the entire config file, but this is the relevant section.

        <Location />
                ProxyPass http://localhost:5555/
                ProxyPassReverse http://localhost:5555/
                ProxyPreserveHost On
                RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
                RequestHeader set "X-Forwarded-SSL" expr=%{HTTPS}
        </Location>

@kcsudeep
Copy link

kcsudeep commented Dec 3, 2019

Thank you. This worked.

@h3ct0rjs
Copy link

Hi Guys,

Sorry for reopening this one, But I haven't figured it out yet, Currently I have the same issue, but in my case I'm using nginx as a reverse proxy. As @cabal95 did mention previously, I've added proxy_set_header Host $host; to my nginx configuration, it looks like this :

server {
          nameserver site.x.com;
          
          location /nuget/ {
             proxy_set_header Host $host;
             proxy_pass http://localhost:5000/;
          }
}

This is not working for me, I'm missing something ? , I'm currently using the latest docker hub image.

Thanks in advance,
Sincerely,
Hector

@h3ct0rjs
Copy link

Hi Guys,
I was checking and just in case that anybody that implements Nginx as reverse proxy, you should add the following headers:

server {
          nameserver site.x.com;

   location / {
             proxy_set_header Host $host;
             proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
             proxy_set_header X-Forwarded-Proto $scheme;
             proxy_set_header X-Forwarded-Host  $host;
             proxy_pass http://localhost:5000/;

          }
}

Please close again this issue.
Thanks in advance,
Sincerely,
H
@cabal95 Thank you very much, you help me a lot. I did the same thing with tcpdump.

@mkonijnenburg
Copy link

Adding HTTPS support has become more urgent today with the latest VS2020 17.3 edition, the following warning/error comes up:

error NU1803: You are running the 'restore' operation with an 'HTTP' source, 'http://nuget.mysite.com:5000/v3/index.json'. Non-HTTPS access will be removed in a future version. Consider migrating to an 'HTTPS' source.

@doxxx
Copy link

doxxx commented Aug 10, 2022

So I was able to enable HTTPS just by modifying the appsettings.json. I installed my SSL certificate into the Windows Certificate Store, in Local Machine -> Personal. Then I added the following to the Kestrel -> Endpoints block in appsettings.json:

"HttpsInlineCertStore": {
  "Url": "https://*:443",
  "Certificate": {
    "Subject": "my-certificate-CN",
    "Store": "My",
    "Location": "LocalMachine",
  }
},

In my case, my certificate is a wildcard so its CN was *.mydomain.com, which is what I put in the Subject field above.

I also had to make sure that BaGet was running under the SYSTEM account so that it could access the Local Machine certificate store.

@doxxx
Copy link

doxxx commented Aug 10, 2022

I also previously had it configured to use a .pfx file with a password, but that's less secure since the password had to be included in the config file in plaintext.

See the Microsoft docs on how to configure Kestrel HTTPS for certificate files/stores/etc.

@embix
Copy link

embix commented Sep 15, 2022

Would be cool if we had a solution that lets us just use the loicsharma/baget:latest image and mount in the cert/key files we got from certbot and it magically works.

@adschmu
Copy link

adschmu commented Apr 4, 2023

This did not work for me with Apache on Ubuntu 22.04 with .NET 6 based BaGet. I had to do the following change in addition to the Apache configuration posted above:

diff --git a/src/BaGet/ConfigureBaGetOptions.cs b/src/BaGet/ConfigureBaGetOptions.cs
index b28a658..52c8a4c 100644
--- a/src/BaGet/ConfigureBaGetOptions.cs
+++ b/src/BaGet/ConfigureBaGetOptions.cs
@@ -69,7 +69,7 @@ public void Configure(FormOptions options)

         public void Configure(ForwardedHeadersOptions options)
         {
-            options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
+            options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedProto;

             // Do not restrict to local network/proxy
             options.KnownNetworks.Clear();

Source: https://soapfault.com/2020/02/24/asp-net-core-reverse-proxy-and-x-forwarded-headers/

@serverkraft
Copy link

I've found a solution to use baget with https. We use baget in docker, so a nginx reverse proxy was implemented.

docker-compose.yml:

version: "3"
services:
  baget:
	image: loicsharma/baget
	container_name: baget
	volumes:
	  - ./baget_data:/var/baget
	  - ./appsettings.json:/app/appsettings.json
	  - ./certs/:/certs:ro
	ports:
	  - "5555:80"
	restart:  unless-stopped
	environment:
	 #DEBUG: "true"
	  VIRTUAL_HOST: baget
	  VIRTUAL_PORT: 80
	env_file:
	 - baget.env

	logging:
	 driver: "json-file"
	 options:
	   max-size: "50m"

  baget_ssl:
   image: nginx
   volumes:
	- ./nginx.conf:/etc/nginx/conf.d/mysite.template
	- ./baget.crt:/etc/ssl/certs/nginx-selfsigned.crt
	- ./baget.key:/etc/ssl/private/nginx-selfsigned.key
	#- ./local-ca.crt:/usr/local/share/ca-certificates/local-ca.crt
   ports:
	- "5543:443"
	#- "9180:80"
   restart:  unless-stopped
   command: /bin/bash -c "cat /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
   logging:
	driver: "json-file"
	options:
	 max-size: "50m"

nginx.conf:

server {
		listen 80;
		listen [::]:80 default_server;
		server_name  baget;
		listen 443 ssl http2 default_server;
		#listen [::]:443 ssl http2 default_server;
		ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
		ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
		#ssl_certificate /etc/ssl/certs/baget.crt;
		#ssl_certificate_key /etc/ssl/private/baget.key;

		client_max_body_size 1280m;
		proxy_read_timeout 600;

		location / {
			proxy_pass http://localhost:5555;
			proxy_set_header X-Forwarded-Proto $scheme;
			proxy_set_header X-Forwarded-Host  $host;
			proxy_set_header X-Forwarded-Port 5543;
			proxy_set_header Host $host:5543;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_http_version 1.1;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "Upgrade";
			access_log off;

		}
		# You may need this to prevent return 404 recursion.
		location = /404.html {
				internal;
		}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests