Jump to content

HOW TO: emby with NGINX - With Windows Specific Tips and CSP options


pir8radio

Recommended Posts

darkassassin07
9 hours ago, rbjtech said:

@pir8radio

Hi - Just a note to say that your original nginx config (still active on Page 1) uses the X-Forwarded-For header command - and I believe this should be removed as it is a potential security issue. (see link from Mozilla below)

My understanding is adding this X-Forwarded-For line may have been the reason people have been compromised with the recent emby LAN spoofing exploit even when using an NGINX reverse proxy ?

I used your original config as a framework when I first set up emby, but I went in-depth to understand each line of it - so I fortunately removed it and just included the X-Real-IP - there is no need to use the X-Forwarded-For.

The only time you would use this, is if you have other trusted reverse proxies in-line - and then you can add them specifically as trusted proxies.

 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For#security_and_privacy_concerns

Maybe it's worth reviewing the original config and even worth putting out a suggestion or recommendation to remove that line ?

@softworkzFYI - I know this is not directly related to emby, but though I'd include you as I presume you will have details on the different types of effected systems - incl those behind a reverse proxy.

 

Removing these lines is a really really bad idea.

 

Those headers are how emby can tell the difference between a proxied connection and just a client connecting directly.

 

 

With them removed; anything connecting to emby via your proxy will appear as a direct connection straight from the ip of your proxy. If it happens to share a lan with your emby server, every connection through it appears to be a lan connection regardless of its true origin.

This is why they exist. Leave them correctly configured the way they are in the example config. People behind proxies configured as given were unaffected as said proxy covered the security hole (it correctly re-set those headers before they reach your emby server, this way clients can't pre-set and abuse them).

 

Besides, this has been patched so that lan IPs are no longer valid within those headers and will be ignored. (if you remove them, you are effectively bypassing that fix and putting yourself back at risk)

 

 

 

The only minor change I'd suggest is swapping "$proxy_add_x_forwarded_for"for "$remote_addr" this will entirely clear the header and set it to the ip of the connecting device instead of adding to the list. Either way is non problematic though as emby only cares about the last ip added, which will always be the device connecting to the proxy when using "$proxy_add_x_forwarded_for".

Edited by darkassassin07
Link to comment
Share on other sites

darkassassin07

The headers:

X-Forwarded-Protocol: https
X-Forwarded-Ssl: on
X-Url-Scheme: https

Each do the same thing; communicate to the backend server (emby in this case) that the connection between the client and proxy used https even if the connection between the proxy and backend server was just plain http.

 

AFAIK Emby doesn't look at these, but @softworkzwould probably have a better idea about that part.

 

  • Like 1
Link to comment
Share on other sites

3 minutes ago, darkassassin07 said:

X-Forwarded-Protocol: https

It's X-Forwarded-Proto, not X-Forwarded-Protocol

2 minutes ago, darkassassin07 said:

AFAIK Emby doesn't look at these, but @softworkzwould probably have a better idea about that part.

Emby evaluates the X-Forwarded-Proto header (none of the others) and provides it internally (accessible to plugins) via the Emby SDK Reference: IRequest.IsSecureConnection property.

As far as I can see, it is not further used by the core server code at this time.

  • Thanks 1
Link to comment
Share on other sites

rbjtech
10 hours ago, softworkz said:

Currently, Emby Server uses the first IP address from the X-FORWARDED-FOR header if available. Only if there's no X-FORWARDED-FOR header, then it will look for X-REAL-IP. 

Thanks @softworkz

Beyond the basics, I'm not experienced in NGINX at all - so may I ask what's the logic to use X-Forwarded-For first (ie look for/approve another proxy in-front of the reverse proxy) THEN add the X-Real-IP data ?

If X-Forwarded-For is used with the $remote address (as well as the X-Real-IP)  - then would you consider this 'safe' ?

To note, if I replace X-Real-IP with X-Forwarded-For in my config - then the real IP is not passed on, I just get the RP IP address as the source. 

As having just X-Real-IP added works fine, then I would consider this the least priviledge option ?

Any thoughts appreciated.  :)

Link to comment
Share on other sites

rbjtech
13 hours ago, darkassassin07 said:

Removing these lines is a really really bad idea.

 

Those headers are how emby can tell the difference between a proxied connection and just a client connecting directly.

 

 

With them removed; anything connecting to emby via your proxy will appear as a direct connection straight from the ip of your proxy. If it happens to share a lan with your emby server, every connection through it appears to be a lan connection regardless of its true origin.

This is why they exist. Leave them correctly configured the way they are in the example config. People behind proxies configured as given were unaffected as said proxy covered the security hole (it correctly re-set those headers before they reach your emby server, this way clients can't pre-set and abuse them).

 

Besides, this has been patched so that lan IPs are no longer valid within those headers and will be ignored. (if you remove them, you are effectively bypassing that fix and putting yourself back at risk)

 

 

 

The only minor change I'd suggest is swapping "$proxy_add_x_forwarded_for"for "$remote_addr" this will entirely clear the header and set it to the ip of the connecting device instead of adding to the list. Either way is non problematic though as emby only cares about the last ip added, which will always be the device connecting to the proxy when using "$proxy_add_x_forwarded_for".

I never said to to remove both lines - I am questioning  the use of XFF - and opening the debate.

My NGINX config is below - all nginx weblogs and obviously emby consider each connection public using it's correct WAN ip.

So why do I need to use XFF ?

To note, the example NGINX RP config does NOT use XFF, only X-Real-IP (https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)

Linode - a well respected site also suggests it is optional and does not need to be used (Use NGINX as a Reverse Proxy | Linode Docs) they use X-Real-IP only by default - they are actually one of the better sites explaining each section of the NGINX config.

So just because it is listed in an Emby post about the subject - doesn't mean it is correct.... ;)

That is why I am questioning it's use ...  I am totally happy to be corrected as my experience with NGINX is very limited, but I am not one to just copy and paste a 'config' from a forum without understanding from an authoritive source on what it does.

proxy_set_header X-Real-IP $remote_addr;  ## Passes the real client IP to the backend server.
#proxy_set_header X-Real-IP $http_CF_Connecting_IP;  ## if you use cloudflare un-comment this line and comment out above line.
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  ## Adds forwarded IP to the list of IPs that were forwarded to the backend serv>#       #proxy_set_header X-Forwarded-For $remote_addr;

 

Edited by rbjtech
Link to comment
Share on other sites

darkassassin07
17 minutes ago, rbjtech said:

I never said to to remove both lines - I am questioning  the use of XFF - and opening the debate.

My NGINX config is below - all nginx weblogs and obviously emby consider each connection public using it's correct WAN ip.

So why do I need to use XFF ?

To note, the example NGINX RP config does NOT use XFF, only X-Real-IP (https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)

Linode - a well respected site also suggests it is optional and does not need to be used (Use NGINX as a Reverse Proxy | Linode Docs) they use X-Real-IP only by default - they are actually one of the better sites explaining each section of the NGINX config.

So just because it is listed in an Emby post about the subject - doesn't mean it is correct.... ;)

That is why I am questioning it's use ...  I am totally happy to be corrected as my experience with NGINX is very limited, but I am not one to just copy and paste a 'config' from a forum without understanding from an authoritive source on what it does.

proxy_set_header X-Real-IP $remote_addr;  ## Passes the real client IP to the backend server.
#proxy_set_header X-Real-IP $http_CF_Connecting_IP;  ## if you use cloudflare un-comment this line and comment out above line.
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  ## Adds forwarded IP to the list of IPs that were forwarded to the backend serv>#       #proxy_set_header X-Forwarded-For $remote_addr;

 

The main reason to set this header is that if you don't, it get's passed as-is from the client. As Emby listens to this header first, it would allow the client to send a header with a lan IP in it masquerading as a lan client (pre-patch. Now they can just spoof a different wan ip).

If you had that line removed prior to the security breach; you were vulnerable to it as well. Even with X-Real-Ip still present.

When it's been explicitly set by your proxy, you know for sure what's in it.

 

It's less consequential now, but would still allow a client to spoof a different ip than what they are connecting from. (ie the ip displayed in your server activity would be whatever the client passes in that header as long as it's not a lan ip anymore.

  • Like 1
Link to comment
Share on other sites

rbjtech
6 hours ago, darkassassin07 said:

The main reason to set this header is that if you don't, it get's passed as-is from the client. As Emby listens to this header first, it would allow the client to send a header with a lan IP in it masquerading as a lan client (pre-patch. Now they can just spoof a different wan ip).

If you had that line removed prior to the security breach; you were vulnerable to it as well. Even with X-Real-Ip still present.

When it's been explicitly set by your proxy, you know for sure what's in it.

 

It's less consequential now, but would still allow a client to spoof a different ip than what they are connecting from. (ie the ip displayed in your server activity would be whatever the client passes in that header as long as it's not a lan ip anymore.

ok thanks.

The XFF line did not exist in my config, and I was not impacted by the issue.  The NGINX weblogs showed no localhost entries.  I did have all users with passwords set but no Admins with remote access, but did have local usage set (for non-admins) with not needing passwords, I still do.

So in summary, do you think the NGINX config below is the best approach ? @pir8radio

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;

 

Link to comment
Share on other sites

darkassassin07
1 minute ago, rbjtech said:

ok thanks.

The line did not exist in my config, and I was not impacted by the issue.  The NGINX weblogs showed no localhost entries.  I did have all users with passwords set but no Admins with remote access, but did have local usage set with no passwords, I still do.

So in summary, do you think the NGINX config below is the best approach ?

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;

 

If you don't have anything else infront of nginx (cloudflare for example) probably your best bet.

 
  • Thanks 1
Link to comment
Share on other sites

Q-Droid
41 minutes ago, rbjtech said:

ok thanks.

The XFF line did not exist in my config, and I was not impacted by the issue.  The NGINX weblogs showed no localhost entries.  I did have all users with passwords set but no Admins with remote access, but did have local usage set (for non-admins) with not needing passwords, I still do.

So in summary, do you think the NGINX config below is the best approach ?

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;

 

Didn't we test this and you did not see the header being passed even though the test included a spoofed header?

 

  • Thanks 1
Link to comment
Share on other sites

rbjtech
17 minutes ago, Q-Droid said:

Didn't we test this and you did not see the header being passed even though the test included a spoofed header?

 

We did.

And I just had the X-Real-IP only, I did not have any XFF set.

This may be because NGINX is not forwarding the XFF anyway - and unless configured to do so (for the reason of NEEDING to because it has previously been forwarded by another listed/trusted proxy) then by omitting the config - it is perfectly safe.

This is what I'm trying to get a conclusive answer to.

Forcing it to the $remote_addr is a good compromise - as at least I have a known outcome on what happens to this header, so I've changed my config to include it.

Link to comment
Share on other sites

  • 3 weeks later...
redjacket69

Hello

just wanted to know if i need to enable "Allow remote connections to this Emby Server." this if i use reverse proxy?

Link to comment
Share on other sites

rbjtech
1 hour ago, redjacket69 said:

Hello

just wanted to know if i need to enable "Allow remote connections to this Emby Server." this if i use reverse proxy?

For the moment yes.

This setting is used for establishing the bandwidth restrictions used on remote connections (via the RP) - so I believe it 'could' be removed (as the RP connects to emby locally anyway) but then it would conside the connection local and not enforce these restrictions.

Just make sure you are NOT forwarding the remote port listed to your emby server and upnp/port mapper is disabled/removed - that way, there is no way a connection can be established to emby directly - all connections will be going via your RP.

Also make sure Secure Connection Mode = Handled by Reverse Proxy.

A lot of this will (hopefully..) be changing soon - as the entire concept of 'local' vs 'remote' is being refactored to increase security.

Edited by rbjtech
Link to comment
Share on other sites

redjacket69
7 hours ago, rbjtech said:

For the moment yes.

This setting is used for establishing the bandwidth restrictions used on remote connections (via the RP) - so I believe it 'could' be removed (as the RP connects to emby locally anyway) but then it would conside the connection local and not enforce these restrictions.

Just make sure you are NOT forwarding the remote port listed to your emby server and upnp/port mapper is disabled/removed - that way, there is no way a connection can be established to emby directly - all connections will be going via your RP.

Also make sure Secure Connection Mode = Handled by Reverse Proxy.

A lot of this will (hopefully..) be changing soon - as the entire concept of 'local' vs 'remote' is being refactored to increase security.

One thing i always got me confused is if i should keep the default port open in firewall if i enable remote connection.

Here is my network config now:

Quote

 

Local http port number: 8096

Local https port number: 8920

Enabled - Allow remote connections to this Emby Server.

Public http port number: 8096

Public https port number: 8920

External domain: example.com

Secure connection mode: Handled by Reverse Proxy

Internet streaming bitrate limit (Mbps): 10

 

 

I'm reverse proxying 127.0.0.1:8096. I want to know if i should keep these two ports, 8096 and 8920 open in firewall. Also i don't think the Internet streaming bitrate limit (Mbps) setting does not work if direct playing,,, at least on reverse proxy with nginx or caddy

Link to comment
Share on other sites

rbjtech

Maybe follow the Reverse Proxy guides would be a good starting point.

But in short - no 'external connections' should be allowed directly to the emby web server - that is the whole point of using a RP.   Obviously 'internal' connections need to be allowed as that is what the RP will be 'forwarding' to.

Link to comment
Share on other sites

redjacket69
2 minutes ago, rbjtech said:

Maybe follow the Reverse Proxy guides would be a good starting point.

But in short - no 'external connections' should be allowed directly to the emby web server - that is the whole point of using a RP.   Obviously 'internal' connections need to be allowed as that is what the RP will be 'forwarding' to.

so i block the public ports? but either way. the speed limit does not work

 

Link to comment
Share on other sites

rbjtech
15 minutes ago, redjacket69 said:

so i block the public ports? but either way. the speed limit does not work

 

You need to pass the WAN IP through the RP or emby will just consider it a LAN connection - the RP guides will show you how to do this.

Once you see the WAN IP on the connection (in the dashboard) then the WAN bandwidth restrictions will apply.

example VPN WAN IP below highlighted below ...

image.png.13a6cc7b3b4b1323c99ad0dff3217783.png

Link to comment
Share on other sites

redjacket69
10 hours ago, rbjtech said:

You need to pass the WAN IP through the RP or emby will just consider it a LAN connection - the RP guides will show you how to do this.

Once you see the WAN IP on the connection (in the dashboard) then the WAN bandwidth restrictions will apply.

example VPN WAN IP below highlighted below ...

image.png.13a6cc7b3b4b1323c99ad0dff3217783.png

yes limit does not work if played directly

Link to comment
Share on other sites

  • 2 months later...
CorruptedHart11

May I ask for an example with multiple services passed through besides emby, for use with other things like a webserver or teamspeak? Do we just add multiple location blocks? 

Link to comment
Share on other sites

rbjtech
8 hours ago, CorruptedHart11 said:

May I ask for an example with multiple services passed through besides emby, for use with other things like a webserver or teamspeak? Do we just add multiple location blocks? 

Exactly - just add more location sections with their own service name and settings under the server section inside your .conf file.   

Then restart the service.

Link to comment
Share on other sites

  • 2 weeks later...
liesenheimer

Hello,

I'm currently running Emby and Nginx both in docker containers on Unraid.  Everything seems to work fine except that clients outside of my local LAN fail to keep track of the "played" status for movies and shows.  Not sure where to start troubleshooting this.  It's been up since February, and it just came to my attention recently.  Any help is greatly appreciated, thanks!

Link to comment
Share on other sites

darkassassin07
3 hours ago, liesenheimer said:

Hello,

I'm currently running Emby and Nginx both in docker containers on Unraid.  Everything seems to work fine except that clients outside of my local LAN fail to keep track of the "played" status for movies and shows.  Not sure where to start troubleshooting this.  It's been up since February, and it just came to my attention recently.  Any help is greatly appreciated, thanks!

This is usually a result of websockets not being passed by the proxy.

 

Be sure you have the line:

 

proxy_set_header Upgrade $http_upgrade;

 

In your server block in nginx.

Edited by darkassassin07
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

liesenheimer
12 hours ago, darkassassin07 said:

This is usually a result of websockets not being passed by the proxy.

 

Be sure you have the line:

 

proxy_set_header Upgrade $http_upgrade;

 

In your server block in nginx.

Thank you for the guidance.  I presume you mean a block of code when you say "server block".  I am not sure how to get there as I think I have a different setup, using the official Nginx docker on Unraid, which has a gui.  Here are some screenshots of my setup.  There is an advanced tab that allows for custom configuration code, but at the bottom is a note about set_header lines; does the line above qualify as such, or does it not because of the proxy_ prefix?  If I have to add a custom location, I guess don't understand what this path is supposed to lead to.

 

Screenshot 2023-09-19 074157.png

Screenshot 2023-09-19 074400.png

Screenshot 2023-09-19 080004.png

Link to comment
Share on other sites

darkassassin07

Ah, yeah things are a little different through the proxy manager.

 

In your third screenshot you have 'websocket support' enabled, which should perform the same function.

 

Perhaps @pir8radiocan help further.

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...
Alexwerilles

Does anyone know a code to limit download speed that works with this @pir8radio config? I never managed to make it work

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...