Jellyfin Forum
HTTPS on Port 443 fails (Ubuntu) - Printable Version

+- Jellyfin Forum (https://forum.jellyfin.org)
+-- Forum: Support (https://forum.jellyfin.org/f-support)
+--- Forum: Troubleshooting (https://forum.jellyfin.org/f-troubleshooting)
+---- Forum: Networking & Access (https://forum.jellyfin.org/f-networking-access)
+---- Thread: HTTPS on Port 443 fails (Ubuntu) (/t-https-on-port-443-fails-ubuntu)



HTTPS on Port 443 fails (Ubuntu) - bitstream - 2025-04-09

Hola

i got Jellyfin running on Ubuntu in a VM. Naked Ubuntu, no other services installed.

HTTP on port 8096 is working fine.
HTTPS on port 8920 is working fine with my letsencrypt cert.

However, when changing HTTPS to port 443, JF fails to start.
netstat shows 443 is not used, so there should be no problem for JF to bind to that port.

From what i understand during startup Kestrel obv. doesn't has the permission to bind to that socket. However, running a little php script opening a listener socket on 443 under user jellyfin works. Any idea why this is not working with JF?


System.Net.Sockets.SocketException (13): Permission denied
  at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
  at System.Net.Sockets.Socket.Bind(EndPoint localEP)
  at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportOptions.CreateDefaultBoundListenSocket(EndPoint endpoint)
  at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionListener.Bind()
  at Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory.BindAsync(EndPoint endpoint, CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.TransportManager.BindAsync(EndPoint endPoint, ConnectionDelegate connectionDelegate, EndpointConfig endpointConfig, CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.<>c__DisplayClass28_01.<<StartAsync>g__OnBind|0>d.MoveNext()
--- End of stack trace from previous location ---
  at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindEndpointAsync(ListenOptions endpoint, AddressBindContext context, CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.EndpointsStrategy.BindAsync(AddressBindContext context, CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.BindAsync(ListenOptions[] listenOptions, AddressBindContext context, Func
2 useHttps, CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication1 application, CancellationToken cancellationToken)
  at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
  at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>b__15_1(IHostedService service, CancellationToken token)
  at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable
1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List1 exceptions, Func3 operation)
  at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken)


RE: HTTPS on Port 443 fails - bitstream - 2025-04-09

Okay, seems to be a Linux problem. Non-root users do not have the permission to bind ports below 1024 by default.

Under Ubuntu, it should be possible to set the related permissions for JF using setcap
https://linux.die.net/man/3/cap_from_text

Concluding /usr/lib/jellyfin/bin/jellyfin is the starting binary, i tried

sudo setcap CAP_NET_BIND_SERVICE=+eip /usr/lib/jellyfin/bin/jellyfin

However, JF still can't bind the port.

Did I incorrectly assume /usr/lib/jellyfin/bin/jellyfin is how JF is started?


RE: HTTPS on Port 443 fails (Ubuntu) - bitstream - 2025-04-09

Other option would be to configure a redirect with iptables:

sudo iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8096
sudo iptables -t nat -I PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8920

And don't forget to make the rules permanent:
apt-get install iptables-persistent
iptables-save > /etc/iptables/rules.v4


RE: HTTPS on Port 443 fails (Ubuntu) - TheDreadPirate - 2025-04-10

We strongly recommend you use a reverse proxy for https connections. And you should definitely avoid putting Jellyfin on port 80 and 443. Jellyfin is not hardened, makes no claims to be, and directly exposing Jellyfin to a common service port is strongly discouraged.


RE: HTTPS on Port 443 fails (Ubuntu) - bitstream - 2025-04-10

Are you saying JF hasn't implemented protection against OWASPTOP10 attacks and similar like i.e. input validation and so on? Is this what you mean with "not hardened"?

How can changing a port make an application more or less secure? When it comes to ports, the question is, who can access which IP in which network segment on which port from where using which protocol. This is what firewalls are for. In my case JF is running on a VM in a non public routed network segment. So no access for any sort of pirates :-).

If I get you right, you suggest to bind JF only on the loopback adapter, not exposing any of its ports on the public interface of the machine and then have a reverse proxy running on the same machine which on the second leg is talking to JF over http on the loopback adapter and is binding https on the public leg on i.e. port 443? Furthermore, in case there should be no application security, on the reverse proxy we also should have running an deep inpection firewall i.e mod security.

Just to make sure we have the same understanding: Running JF on Host A with http on a port other than 80 and having a reverse proxy running on host B, would leave all traffic between A and B unencrypted. This indeed would be a major concern, as in this case i.e. user passwords would be transmitted unencrypted. So in a scenario like this, https or any other kind of secure tunnel between A and B would be required.


RE: HTTPS on Port 443 fails (Ubuntu) - TheDreadPirate - 2025-04-10

(2025-04-10, 04:03 PM)bitstream Wrote: Are you saying JF hasn't implemented protection against OWASPTOP10 attacks and similar like i.e. input validation and so on? Is this what you mean with "not hardened"?

I don't know what exploits or attacks, specifically, Jellyfin is vulnerable to.  We address security vulnerabilities that we are aware of that directly affect Jellyfin, like ensuring that authentication cannot be bypassed.  But when it comes to how Jellyfin handles HTTPS, specifically, there is zero configurability regarding what ciphers to allow, server vs client cipher preference, etc.  Nor does Jellyfin make claims to being secure with the way it handles HTTPS.  Which is why we very very explicitly say to use a reverse proxy when setting up HTTPS for remote access.

(2025-04-10, 04:03 PM)bitstream Wrote: How can changing a port make an application more or less secure? When it comes to ports, the question is, who can access which IP in which network segment on which port from where using which protocol. This is what firewalls are for. In my case JF is running on a VM in a non public routed network segment. So no access for any sort of pirates :-).

Script kiddies and low effort hackers typically scan common service ports.  21 (telnet), 22 (ssh), 80 (http), 443 (https), 3389 (RDP), 8080 (common alt http port), 53 (dns), etc.  Less common services are usually not scanned and any that bother to randomly scan ports will only try a few random ports before moving on.

By having Jellyfin on port 80/443, you are increasing the visibility of Jellyfin.  Which, as I said, makes no claims to be secure.  Even if someone exposes Jellyfin directly to the Internet on its original port 8096, we still strongly discourage that.

Let a hardened reverse proxy handle external connections and don't expose Jellyfin directly to the Internet if you don't have to.

Your firewall doesn't mean anything since you are allowing unsolicited traffic in on whatever port Jellyfin or your reverse proxy is listening on.  So it is up to the app running on that port to be secure.

(2025-04-10, 04:03 PM)bitstream Wrote: If I get you right, you suggest to bind JF only on the loopback adapter, not exposing any of its ports on the public interface of the machine and then have a reverse proxy running on the same machine which on the second leg is talking to JF over http on the loopback adapter and is binding https on the public leg on i.e. port 443? Furthermore, in case there should be no application security, on the reverse proxy we also should have running an deep inpection firewall i.e mod security.

Just to make sure we have the same understanding: Running JF on Host A with http on a port other than 80 and having a reverse proxy running on host B, would leave all traffic between A and B unencrypted. This indeed would be a major concern, as in this case i.e. user passwords would be transmitted unencrypted. So in a scenario like this, https or any other kind of secure tunnel between A and B would be required.

No, you do NOT need to bind Jellyfin exclusively to the loopback interface.  You could, but you don't have to.  If Jellyfin is on port 8096, the reverse proxy would send traffic on that port.  That COULD be the loopback, but doesn't have to be.  And clients would connect via the reverse proxy.

If the reverse proxy is on another host on the same LAN, assuming the LAN is your home network, the traffic being unencrypted between the proxy and Jellyfin is not a concern.  If the reverse proxy is on a host outside of your LAN, the preferred method to protect that leg is to use a VPN like wireguard.  This ensures that ONLY the reverse proxy can communicate to Jellyfin.

All of this only applies if you plan to access Jellyfin outside of your network.

If you plan to only access Jellyfin from the same LAN the server is running on, none of this applies.  Running Jellyfin on port 8096 is preferred in this situation since most clients will attempt a connection on that port when http is specified as the protocol and no port is defined in the URL.


RE: HTTPS on Port 443 fails (Ubuntu) - bitstream - 2025-04-11

We're half way on the same page, half way not :-)



Re: HTTPS/TLS
I understand JF does not offer any kind of HTTPS/SSL/TLS configuration other than the port and providing the cert to be used. I know that not being able to restrict the SSL/TLS version and ciphers to be used, has to be seen as a security risk. Knowing this, it's still better to use HTTPS than to use http without encryption, sending all communication incl. passwords in cleartext. So "don't use JF HTTPS" generally is a bad advice. This needs to be formulated more differentiated.



Re: Integration pattern
The only (if not using an other secure tunnel) acceptable intergration pattern allowing to use http in communication with JF would be to bind JF to the loopback adapter only and have a reverse proxy running on the same machine talking to JF on the second leg. JF then also should be configured to only take requests from the reverse proxy. This is the only way to make sure JF's http port is not exposed to the outside of the machine. Still, that's not perfect, as the http connection could be interfered within the machine. However this would most probably require to take over the machine, where intercepting a http connection isn't the main problem then.
The moment the reverse proxy is not running on the same machine, meaning communication is flowing through a virtual or physical network between the reverse proxy and JF, unencrpyted communication is a severe security risk (passwords are transmitted in clear text and can be intercepte on the network) and using https on JF on the second leg has to be considered far better than using http.

1) Only if reverse proxy and JF are running on the same machine:
pattern A: client -> https -> reverse proxy -> http/loopback -> JF/loopback
https would still be better:
pattern B: client -> https -> reverse proxy -> https/loopback -> JF/loopback

All other scenarios:
pattern C: client -> https -> reverse proxy -> https -> JF

2) If you can't have or don't want a reverse proxy running for what ever reason:
pattern C: client -> https -> JF
This pattern should not be chosen if the machine is exposed to a non-trusted, public or routed network.
However it's far better than
[dont do] pattern D: client -> http -> JF

Finally: Without knowing what SSL/TLS stack JF is using, moderns stacks are expected to support TLS configurability. From what I read in the forum, it seems to be by intention to not add configurability options to JF. Argument is, that there are reverse proxies offering this functionality, so why should JF implement it? Did I get this correct?
While I agree to this if an application runs in an application runner, I'd say it's a best practise today to encrypt communication the moment information leaves the application context. So if JF would come bundled with/in an application runner, I would agree.



Re: Security by obscurity
Is considered a security anti-pattern. Script kiddies or not, scanning the whole portrange of a machine is done in the fraction of a second and moving ports doesn't change anything. This is not going to make JF more or less secure.


RE: HTTPS on Port 443 fails (Ubuntu) - TheDreadPirate - 2025-04-11

(2025-04-11, 01:19 PM)bitstream Wrote: We're half way on the same page, half way not :-)

Re: HTTPS/TLS
I understand JF does not offer any kind of HTTPS/SSL/TLS configuration other than the port and providing the cert to be used. I know that not being able to restrict the SSL/TLS version and ciphers to be used, has to be seen as a security risk. Knowing this, it's still better to use HTTPS than to use http without encryption, sending all communication incl. passwords in cleartext. So "don't use JF HTTPS" generally is a bad advice. This needs to be formulated more differentiated.

Our advise is "use a reverse proxy if you need HTTPS".  If you need secure comms between a remote proxy and Jellyfin, use a VPN.  Wireguard is dead simple, low overhead, fast AF (on Linux), and perfect for site-to-site comms.  If your setup is local only, don't bother.  If you have someone on your local network that you are concerned about reading traffic, you should probably deal with that.

(2025-04-11, 01:19 PM)bitstream Wrote: Re: Integration pattern
The only (if not using an other secure tunnel) acceptable intergration pattern allowing to use http in communication with JF would be to bind JF to the loopback adapter only and have a reverse proxy running on the same machine talking to JF on the second leg. JF then also should be configured to only take requests from the reverse proxy. This is the only way to make sure JF's http port is not exposed to the outside of the machine. Still, that's not perfect, as the http connection could be interfered within the machine. However this would most probably require to take over the machine, where intercepting a http connection isn't the main problem then.
The moment the reverse proxy is not running on the same machine, meaning communication is flowing through a virtual or physical network between the reverse proxy and JF, unencrpyted communication is a severe security risk (passwords are transmitted in clear text and can be intercepte on the network) and using https on JF on the second leg has to be considered far better than using http.

1) Only if reverse proxy and JF are running on the same machine:
pattern A: client -> https -> reverse proxy -> http/loopback -> JF/loopback
https would still be better:
pattern B: client -> https -> reverse proxy -> https/loopback -> JF/loopback

All other scenarios:
pattern C: client -> https -> reverse proxy -> https -> JF

2) If you can't have or don't want a reverse proxy running for what ever reason:
pattern C: client -> https -> JF
This pattern should not be chosen if the machine is exposed to a non-trusted, public or routed network.
However it's far better than
[dont do] pattern D: client -> http -> JF

Finally: Without knowing what SSL/TLS stack JF is using, moderns stacks are expected to support TLS configurability. From what I read in the forum, it seems to be by intention to not add configurability options to JF. Argument is, that there are reverse proxies offering this functionality, so why should JF implement it? Did I get this correct?
While I agree to this if an application runs in an application runner, I'd say it's a best practise today to encrypt communication the moment information leaves the application context. So if JF would come bundled with/in an application runner, I would agree.

Regarding 1a and 1b, if you don't need or want local clients to connect directly to port 8096 it is definitely 100% viable to only bind Jellyfin to the local loopback when the RP is on the same host.

I run Jellyfin in Docker, with plain Nginx on the host, and use "expose" in docker vs port publishing.  Since only the server is aware of the Docker IP space, I achieve a similar result.  Though not 100% equivalent since I could, hypothetically, add a route in my router to send traffic for that docker IP space to the Docker host's LAN interface.

But a lot of users do want local only clients (think Android TV and Roku) to still be able to find their server automatically via service discovery.  Which would require that jellyfin bind to the LAN interface.

1b seems overkill.  If you have something running on the server that could intercept the plaintext traffic on the local loopback, it could do the same for https since it would probably have access to the key or have access to the process or memory space to read the traffic pre-encryption.

Same with 1c.  If you have a bad actor capable of reading the traffic on your LAN, you should probably deal with that.

Having said that, I get the "better safe than sorry" mentality.  But 1c is not strictly necessary and not something an average person should worry about or bother doing.

And, for whatever reason, you can't or don't want a reverse proxy, yes HTTPS directly from Jellyfin is better than nothing.

(2025-04-11, 01:19 PM)bitstream Wrote: Re: Security by obscurity
Is considered a security anti-pattern. Script kiddies or not, scanning the whole portrange of a machine is done in the fraction of a second and moving ports doesn't change anything. This is not going to make JF more or less secure.

If obscurity is your only security measure, yes.  You cannot say your setup is secure.  But it is a way to reduce risk by reducing the number of attempts.

OpenWRT supports writing dropped connection attempts to log, and then supports sending those logs via rsyslog to a remote host.  I have fail2ban read those logs to look for attempts to scan for services and then fail2ban adds an iptables rule to block the offender if they do happen to find the port my services run on.  I am intimately familiar with how script kiddies typically behave and they do not scan every port nor scan a lot of ports.  They scan common service ports, a handful of random ports, and move on.  The kid of person that would run these kinds of scans are looking for low hanging fruit.  Unpatched or EOL systems with known, often old, vulnerabilities.   I'm not saying it does not ever happen.  But it is unlikely that they will scan every port.

Code:
### router log, attempted telnet connection
2025-04-09T16:15:25-04:00 gateway kernel: [36859.043275] drop wan in: IN=eth1 OUT= MAC=<Router MAC> SRC=45.71.85.44 DST=<My IPv4 Address> LEN=40 TOS=0x00 PREC=0x00 TTL=53 ID=37875 PROTO=TCP SPT=22727 DPT=23 WINDOW=33636 RES=0x00 SYN URGP=0

### fail2ban log
2025-04-09 16:15:26,027 fail2ban.filter        [2108361]: INFO    [router] Found 45.71.85.44 - 2025-04-09 16:15:25
2025-04-09 16:15:26,029 fail2ban.actions        [2108361]: NOTICE  [router] Ban 45.71.85.44

Moving Jellyfin itself to a port that is very much going to be scanned frequently is less than ideal.  Obscurity is better than nothing.  But obscurity should be an extra step on top of a properly secure setup.  And that means using a reverse proxy for external HTTPS connections for Jellyfin.