allinurl / goaccess

GoAccess is a real-time web log analyzer and interactive viewer that runs in a terminal in *nix systems or through your browser.
https://goaccess.io
MIT License
18.17k stars 1.1k forks source link

goaccess websocket behind reverse proxy is not working #1280

Open subzero01 opened 5 years ago

subzero01 commented 5 years ago

If the parameter --ws-url=wss://FQDN/ws is used the browser tries to connect to an invalid url as wss://FQDN/ws:7890.

I'm using nginx as reverse proxy.

allinurl commented 5 years ago

You can specify the reverse port as well, e.g.,--ws-url=wss://FQDN:8080

subzero01 commented 5 years ago

No I can not. The only open port is 443. Port 80 is redirected to 443. There is no option to open an additional port. If I specify wss://FQDN:443/ws goaccess will try to open the WS listen port on 443 which is used by the proxy. In this case it is nginx. I fixed it temporary by changing the app.js to use the --ws-url as is without the code applying the port. websocket.patch.txt

allinurl commented 5 years ago

Not sure what you mean you cannot specify the port. --ws-url=wss://FQDN:PORT while at the same time you can always change --port=PORT. e.g.,

goaccess access.log --log-format=COMBINED --port=9870 --ws-url=wss://goaccess.io:8970 --real-time-html -o out.html
subzero01 commented 5 years ago

OK. I will explain my setup:

I have a proxy listening on MY_FQDN:443. On the same machine goaccess is running as a daemon including --ws-url=wss://MY_FQDN/ws. If the browser connects to https://MY_FQDN/ the browser tries to open a connection to wss://MY_FQDN/ws:7890. <-- this is the issue.

See my patch in my previous comment

lencell commented 5 years ago

I'll allow myself to comment, having a working setup with a reverse proxy although I'm not using Nginx(I use HaProxy) and I think it's your configuration which needs to be tweaked, if you only have the 443 port available you should try starting goaccess with --ws-url=wss://MY_FQDN:443/ws --port 7890 for the websocket relevant options, and then configure your Nginx serverblock to reverse proxy all requests with an URI starting by /ws to the websocket with something like:

location /ws {
    proxy_pass http://localhost:7890;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

Note that you might have to try/tweak the nginx configuration as I have not tested it

subzero01 commented 5 years ago

Hello, It is not an nginx setup issue. If I use your proposal the client is connecting successfully. It is a little bit confusing to specify the port number in the url which is known as standard port for a specific protocol. The url the client is using now is https://MY_FQDN/ws when I use --ws-url=wss://MY_FQDN:443/ws --port 7890

On the other hand if I ommit the port number the portnumber from the local server is appended to the url and not appended to the hostname inside the url. https://MY_FQDN/ws:7890 when I use --ws-url=wss://MY_FQDN/ws --port 7890

This is the issue and of course makes no sense

lencell commented 5 years ago

Hi,

I am myself a bit confused by your answer, so is it working with my proposal ?(it should) Regarding the port, one could argue that websocket being an extension of html5 and tied to http, it's still kinda logical to make it go through http(s) ports, although keep in mind that I suggested this configuration solely because you said that port 443 was the only port you had open and available (unless I was mistaken), you can of course use any port you want, the only thing to keep in mind is:

If you want 7890 you can just put --ws-url=wss://MY_FQDN:7890/ws as an argument, or whatever port you would prefer there. It will be the port requested by your clients in their browsers.

Regards.

subzero01 commented 5 years ago

Hi,

From my point of view ws:// implies port 80 and wss:// implies 443. It is confusing a. to specify a standard port and b. if i don't specify the port the browser tries to connect to an invalid url

If you don't agree with this close this issue as "won't fix"

PitySOFT commented 5 years ago

I have the same issue with my setup. I have nginx as a proxy server to serve secure websocket and the port is appended to the wss url.

It will be nice to ignore the port append if the port is set as 0.

Zidichy commented 5 years ago

Here you go, fully working goaccess subdomain.conf in RP :) https://github.com/Zidichy/Server/blob/master/proxy-confs/goaccess.conf

MatthiasLohr commented 4 years ago

Is there any option for not hardcoding the reverse proxies hostname in the goaccess configuration?

Currently, I have: domain.tld:443/stats/ws - is there any option to get rid of domain.tld in the configuration? I want to run the same setup on different nodes with different hostnames. Somehow I would expect that the link resolution is similar to HTML: If you specify a relative path, it's based on the current directory. If you specifiy an absolute path, it's based on the current host. But I can't get that working with goaccess. Any ideas?

wilyarti commented 4 years ago

I'll allow myself to comment, having a working setup with a reverse proxy although I'm not using Nginx(I use HaProxy) and I think it's your configuration which needs to be tweaked, if you only have the 443 port available you should try starting goaccess with --ws-url=wss://MY_FQDN:443/ws --port 7890 for the websocket relevant options, and then configure your Nginx serverblock to reverse proxy all requests with an URI starting by /ws to the websocket with something like:

location /ws {
    proxy_pass http://localhost:7890;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
}

Note that you might have to try/tweak the nginx configuration as I have not tested it

I can confirm that this works for me. It allows for the entire session to be encrypted. I placed the location in the HTTPS block.

http {
upstream myapp {
        server 127.0.0.1:8080;
    }
server {
        listen       443 ssl http2;
        server_name  localhost;

        ssl on;
        ssl_certificate      domain.cert.pem;
        ssl_certificate_key  private.key.pem;
        location / {
            proxy_pass http://myapp;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        location /ws {
                     proxy_pass http://localhost:7890;
                     proxy_http_version 1.1;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection "Upgrade";
        }
    }
}
MatthiasLohr commented 4 years ago

That still leaves the question how you can get rid of MY_FQDN in goaccess options. If not specified, it should automatically take the current host or just use a relative URL for the websocket.

wilyarti commented 4 years ago

That still leaves the question how you can get rid of MY_FQDN in goaccess options. If not specified, it should automatically take the current host or just use a relative URL for the websocket.

I specified my FQDN in the --ws-url option and everything works just fine.

lencell commented 4 years ago

Is there any option for not hardcoding the reverse proxies hostname in the goaccess configuration?

Currently, I have: domain.tld:443/stats/ws - is there any option to get rid of domain.tld in the configuration? I want to run the same setup on different nodes with different hostnames. Somehow I would expect that the link resolution is similar to HTML: If you specify a relative path, it's based on the current directory. If you specifiy an absolute path, it's based on the current host. But I can't get that working with goaccess. Any ideas?

I think you could easily solve that problem either by using a wrapper script that would call goaccess with the option --ws-url=wss://$(hostname --fqdn):PORT/URI on its command line, or better through a SystemD unit or whatever is used by your system to manage services

Edit: Although I'm not sure this is the right place to discuss this as this seems pretty unrelated to the original problem.