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 SSL to streams #3789

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open

Conversation

jbowring
Copy link

@jbowring jbowring commented Jun 2, 2024

Support for SSL for streams with TCP forwarding enabled. Uses the same web interface as creating a new Proxy Host for adding SSL.

Screenshot 2024-06-02 at 20 38 48 image

Details

An Nginx stream config created with this SSL feature looks like this:

# ------------------------------------------------------------
# 1883 TCP: 1 UDP: 1
# ------------------------------------------------------------

server {
  listen 1883 ssl;
  listen [::]:1883 ssl;

  # Let's Encrypt SSL
  include conf.d/include/ssl-cache-stream.conf;
  include conf.d/include/ssl-ciphers.conf;
  ssl_certificate /etc/letsencrypt/live/npm-9/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/npm-9/privkey.pem;

  proxy_pass google.com:443;

  # Custom
  include /data/nginx/custom/server_stream[.]conf;
  include /data/nginx/custom/server_stream_tcp[.]conf;
}

server {
  listen 1883 udp;
  listen [::]:1883 udp;

  proxy_pass google.com:443;

  # Custom
  include /data/nginx/custom/server_stream[.]conf;
  include /data/nginx/custom/server_stream_udp[.]conf;
}

Nginx doesn't allow stream and http blocks to share an SSL cache, so all streams have a separate SSL cache defined in ssl-cache-stream.conf:

ssl_session_cache shared:SSL_stream:50m;

Use a DNS Challenge is forced as streams cannot perform HTTP authentication for issuing certificates.

Streams do not have domain names associated with them in the database or displayed in the UI, as streams are not proxied by hostname but exclusively by port.

@jbowring
Copy link
Author

jbowring commented Jun 3, 2024

Related: #3368 #2542 #1829 #795

@RobertPosluszny
Copy link

RobertPosluszny commented Jun 17, 2024

I tested this using my custom SSL certificate running RTMPS from OBS and Zoom to RTMP for Owncast and it worked great! Zoom showed enhanced security because of RTMPS and SSL. The only issue I ran into is if I edited a stream (in the NPM GUI) it would default back to the default stream config template and remove the new SSL information. So I had to delete the stream and add it again and make sure not to edit it. But works perfectly fine if you don't edit a stream after creating it.

Edit: Resolved in 207dbb2

@RobertPosluszny
Copy link

@jbowring Do you have plans to update this PR with future releases?

@jbowring
Copy link
Author

@RobertPosluszny thanks for testing this PR and your feedback. I think I've found the issue you described and fixed it, please check and let me know!

I'll do some more testing myself and then update this PR with a pull from the develop branch.

@jbowring
Copy link
Author

@jc21 what else needs to be done before this PR can be merged? Thanks.

@RobertPosluszny
Copy link

@jbowring looks like the issue of editing stream settings after creation was resolved! Thanks!

@JanzenJohn
Copy link

JanzenJohn commented Sep 29, 2024

When testing the linked CI image the following error is shown in the browser console when trying to create a stream

TypeError: e[t] is undefined
    r https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:1
    190 https://MY-DOMAIN/js/14.bundle.14.js?v=2.11.3:1
    190 https://MY-DOMAIN/js/14.bundle.14.js?v=2.11.3:1
    r https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:1
    showNginxStreamForm https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    promise callback*showNginxStreamForm https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    action https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    click ui.action@https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    dispatch https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    handle https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    add https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    on https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegate https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    _ensureElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    View https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    constructor https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showEmpty https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    promise callback*onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    O https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    render https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    ae https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    show https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showChildView https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showAppContent https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:310
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    promise callback*showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    Ze https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    s https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
[main.bundle.js:1:1930](https://MY-DOMAIN/js/main.bundle.js?v=2.11.3)
    oe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:1
    (Async: promise callback)
    showNginxStreamForm https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    action https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    click @ui.action https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    dispatch https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    handle https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    (Async: EventListener.handleEvent)
    add https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    on https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegate https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    _ensureElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    View https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    constructor https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showEmpty https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    (Async: promise callback)
    onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    O https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    render https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    ae https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    show https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showChildView https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showAppContent https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:310
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    (Async: promise callback)
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    Ze https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    s https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
Uncaught (in promise) TypeError: e[t] is undefined
    r https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:1
    190 https://MY-DOMAIN/js/14.bundle.14.js?v=2.11.3:1
    190 https://MY-DOMAIN/js/14.bundle.14.js?v=2.11.3:1
    r https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:1
    showNginxStreamForm https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    promise callback*showNginxStreamForm https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    action https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    click ui.action@https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    dispatch https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    handle https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    add https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    on https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegate https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    _ensureElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    View https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    constructor https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showEmpty https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    promise callback*onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    O https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    render https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    ae https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    show https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showChildView https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showAppContent https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:310
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    promise callback*showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    Ze https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    s https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
[main.bundle.js:1:356](https://MY-DOMAIN/js/main.bundle.js?v=2.11.3)
    oe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:1
    (Async: promise callback)
    showNginxStreamForm https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    action https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    click @ui.action https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    dispatch https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    handle https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    (Async: EventListener.handleEvent)
    add https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    each https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:16
    xe https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    on https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegate https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    delegateEvents https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    setElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    _ensureElement https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    View https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    constructor https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showEmpty https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    (Async: promise callback)
    onRender https://MY-DOMAIN/js/9.bundle.9.js?v=2.11.3:1
    O https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    render https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    ae https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    show https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showChildView https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showAppContent https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:310
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    (Async: promise callback)
    showNginxStream https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:27
    Ze https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    i https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    s https://MY-DOMAIN/js/main.bundle.js?v=2.11.3:3
    

@RobertPosluszny
Copy link

@jbowring any way to update this PR to keep in line with the latest updates? Is there a way I can help keep that in line until this PR gets merged into develop or latest?

@aaron-neal
Copy link

This would be such a useful feature for anyone trying to secure their MQTT servers to the outside world, thanks for doing it, would be amazing to see this eventually merged to main.

@jbowring
Copy link
Author

@RobertPosluszny sorry I've been unable to maintain this for a while. I've added you as a collaborator to my repository; feel free to keep it up to date and update this pull request.

@alphalove
Copy link

Hello, like a lot of people I'd really like to get SSL for MQTT working within NPM.

The dock image mentioned above at jc21/nginx-proxy-manager:github-pr-3789, it no longer there. I a way I can get this docker image?

Thanks in advance!

@jbowring
Copy link
Author

jbowring commented Dec 1, 2024

The image built above (build 7) doesn’t actually work, there’s an issue with the schema somewhere. I’ll update it when I’ve fixed the problem. Please don’t use it in the meantime.

@alphalove
Copy link

@jbowring - thanks for your effort on integrating SSL for streams, its really appreciated. This will be a great feature for NPM. Given the number of open pull requests, looks like being the NPM maintainer might be a full time job!

@nginxproxymanagerci
Copy link

Docker Image for build 13 is available on
DockerHub
as nginxproxymanager/nginx-proxy-manager-dev:pr-3789

Note: ensure you backup your NPM instance before testing this image! Especially if there are database changes
Note: this is a different docker image namespace than the official image

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

Successfully merging this pull request may close these issues.

6 participants