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
17.88k stars 1.09k forks source link

Binding WSS to 127.0.0.1 prevents realtime output from working #2093

Closed globalistas closed 3 years ago

globalistas commented 3 years ago

I have a live server with Goaccess that's connected directy to the internet and therefore I would like the WSS only be accessible for internal connections from the same machine. I mean, that's all it needs, no? But adding

--addr=127.0.0.1

I get a realtime html output that does not refresh. Am I doing something wrong?

P.S. Is it maybe safe to just leave everything as is? I've already restricted access to report.html in my Nginx site confirguration to a single IP, so...

0bi-w6n-K3nobi commented 3 years ago

Hi @globalistas

First of all, I will do a small questionnaire to understand your problem:

Either way, you can use a PORT other than 443 and block it on your server's firewall --- ex. 4443. And, if the server is not your personal machine, you can release port 4443 on firewall only to access from your IP.

There is another possibility if the server is not your machine --- use SSH with port redirection. In this case, you can keep IP 127.0.0.1 port 443 and use the command:

ssh -L 127.0.0.1:5443:127.0.0.1:443 server

After connecting to the server, just type in the browser of your choice:

https://127.0.0.1:5443/URI-THAT-YOU-CHOICED

However, access will only be available as long as you maintain the SSH connection.

I hope I helped you. If the explanation does not clarify your doubts, feel free to give and ask for more information.

globalistas commented 3 years ago

Hi @0bi-w6n-K3nobi

this is a VPS with just two network interfaces: eth0 (with an internet IP) and the loopback 127.0.0.1.

Goaccess realtime works fine with running without a bind address specified and yes I've already configured it to use my SSL cert. I've also restricted access to https://VPSIP/report.html to a single IP in Nginx.

I've also changed the WSS port to a different number X. Problem is, X is therefore open to the internet but I believe it does not need to be. Hence why I tried to bind WSS to localhost, but then while I can still access report.html it never refreshes with new data.

I don't have any FW rules specified on this VPS as it's basically only running a web server (ports 80 and 443) and SSH (secured down).

Can you maybe post a quick guide on how to proceed in this scenario? In your suggestions above, I'm not understanding the relevance of port 443 and I also don't wanna resort to SSH port redirection.

Many thanks!

0bi-w6n-K3nobi commented 3 years ago

Hi @globalistas

OK ... I believe I now understand your scenario. In fact, you still can't get it to work even as a public IP.

Well ... let's start. The real-time monitoring mode needs a few extra steps to work. In fact, it is important to know that GoAccess uses a feature called WebSocket. And how does it work? --- When you access report.html through your browser, create a WebSocket connection with the server. And in this way, in short periods of time, the server sends the information to the client, who receives it and generates the graphs and tables in real time. At this point it is important to know that the Server needs this to send the information. On the other hand, the report.html file will be generated initially, processing a few lines from the LOGFILE, and soon afterwards it is no longer modified. This is the correct behavior and you don't have to worry about it.

Well ... I hope you have understood this far.

I also have a similar configuration, where I access my sites through NGinX as a cache. In my case, I have a different scenario:

I also found it a little difficult to set up monitoring. I did it first on Apache --- it was quite frustrating! Then I moved on to CONF for NGinX.

Okay. Let's get down to business. First of all, correct me if I am wrong, you will want to access through the public IP --- or --- Do you will use VPN to be on the same network as the server? In the 1st case, you will use NGinX as a proxy for the report.html as well as the WebSocket connection. This is the big ace in the hole, to make monitoring work.

Soon, I will make a small tutorial and indicate other references for you to better understand the process.

Hi @allinurl, would you have any explanatory goods to offer?

I'll talk to you soon.

globalistas commented 3 years ago

"In fact, you still can't get it to work even as a public IP."

Actually, it works just fine on the public IP. But I worry the open port is a security liability.

And I would prefer to avoid implementing another tool (like a VPN) to achieve my goal.

0bi-w6n-K3nobi commented 3 years ago

Why do you create a rule for access? Like a authetication user/password... You can see more here.

If you have a static IP than can release only for your IP.

globalistas commented 3 years ago

I have already secured the access to report.html, restricting it to only my IP. But the WSS port is open for everybody, that's the issue. Feel free to reach me at globalist#9309 on Discord to continue this chat. :)

0bi-w6n-K3nobi commented 3 years ago

Well ... What I propose, which is very simple in theory, is that you also do the WSS proxy. In this case, you will running GoAccess binding on localhost /127.0.0.1 and so use NGinX for transparent proxy. Similar to what you use for the report.hml, and you also consider putting the same security.

This configuration in NGinX is the tutorial I propose. I.E. Use NGinX as the WebSocket proxy for GoAccess. Thus adding the same security as the report.html.

I hope it has made me clearer now.

globalistas commented 3 years ago

Can you please specify exactly the Nginx configuration to enable such setup, and the goaccess launch command to go along with it? Many thanks!

For now, I am just aliasing report.html like this in my site's server block:

location /report.html {
        alias /var/www/html/report.html;
        allow my ip addreess;
        deny all;
}
allinurl commented 3 years ago

If you bind a socket for receiving data to a specific address you can only receive data sent to this specific IP address. For example, if you bind to 127.0.0.1 you will be able to receive data from your own system but not from some other system on the local network, because they cannot send data to your 127.0.0.1: for one any data to 127.0.0.1 will be sent to their own 127.0.0.1 and second your 127.0.0.1 is an address on your internal loopback interface which is not reachable from outside

Thus goaccess binds to 0.0.0.0 by default.

What @0bi-w6n-K3nobi suggested sounds like a good solution.

You can also add a rule to your firewall and block all IPs reaching the WSS port except your IP. Also, upstream recently added the ability to use a unix domain socket, this will be pushed out in the upcoming release.

globalistas commented 3 years ago

@allinurl I guess I'm just not comprehending what is the actual WSS client here? I'm assuming the WSS server part runs on localhost (127.0.0.1:7890) and the client part is the goaccess command, which also runs on the same host and thus should be able to call localhost:8790 to get the data through the socket.

And then, we have another part (but a wholly different connection) which is my web browser, connecting on port 80 or 443 to the VPS machine, to read the contents of report.html. And thus I do not understand, why WSS, for all intents and purposes of this scenario, cannnot work while bound to just localhost?

You are making it sound like my browser is the actual client of WSS, and thus needs to be able to access the VPS on port 7890, but this somehow doesn't make sense to me, becayse the browser is just accessing report.html on port 443.

I hope I've explained my confusion properly. :)

allinurl commented 3 years ago

@globalistas Good question. The browser is indeed the client. When you open the html report, the browser opens the HTML file and that's transferred via HTTPS. However, as soon as it opens the report, the report attempts to connect directly to goaccess' web socket server via 7890, if it succeeds, your browser keeps a connection to it.

As @0bi-w6n-K3nobi indicated, you can proxy the connection if you want to avoid that step.

globalistas commented 3 years ago

OK I see now, thanks. Well, I'm really just a novice when it comes to Nginx/linux and so hoping @0bi-w6n-K3nobi can provide me with some specific nginx config lines and the command line to run goaccess to go along with it.

0bi-w6n-K3nobi commented 3 years ago

Hi @globalistas.

Oh man. I was so busy yesterday, a lot of task in work and chores at home. Wel... What @allinurl tried explain to you is was that I trie too. So sorry if I don't be clear.

I will try explain about NGinX's CONF and GoAccess' parameters that afect WebSocket address and conection with browser/client.

Wait for the next post soon as possible.

0bi-w6n-K3nobi commented 3 years ago

Hi @globalistas

Let's get down to business.

Firstly, I will talk about GoAccess' parameters than interfere in WebSocket server and client' connection. Almost of them are optional or have a default value that so good. However, if you will want more than 1 instance of GoAccess it will be need change these values. It are listed below:

OK... Well, I hope be clear until here. Go on to NGinX's CONF Site's CONF into NGinX. It did shold be like:

##  See more details at https://www.nginx.com/blog/websocket-nginx/

##  GoAccess at --addr and --port
upstream ga_ws {
    server 127.0.0.1:7890;   
}

map $http_upgrade $connection_upgrade {  
    default upgrade;
    ''      close;
}

##  GoAccess at --ws-url
location /wss/ {
   allow my ip addreess;
   deny all;

   proxy_pass         http://ga_ws;  ##  Use only HTTPS if you KEEP the TLS/SSL certificate,
                                 ##  But you NO need it.
   proxy_set_header   Upgrade $http_upgrade;
   proxy_set_header   Connection $connection_upgrade;
   proxy_buffering    off;
   proxy_read_timeout 7d;
   proxy_set_header   Host $host;
}

location /report.html {
    alias /var/www/html/report.html;
    allow my ip addreess;
    deny all;
}

I hope the explanations are reasonably didactic.

And finally... Learn more about GoAccess Tool. It is great!

globalistas commented 3 years ago

@0bi-w6n-K3nobi "Go on to NGinX's CONF. It did shold be like:"

Do you mean I should append that into the /etc/nginx/nginx.conf file?

Reason I ask is I've been putting

location /report.html {
    alias /var/www/html/report.html;
    allow MY IP;
    deny all;
    }

not into /etc/nginx/nginx.conf , but rather into the /etc/nginx/sites-enabled/<mysitefile> file... So I'm a bit confused on this account.

Thanks!

0bi-w6n-K3nobi commented 3 years ago

Hi @globalistas

Yeah... Ok, I seem that you use Ubuntu. I meant Site's CONF into NGinX. So, the second ones -- I.E. /etc/nginx/sites-enabled/<mysitefile> file.

globalistas commented 3 years ago

@0bi-w6n-K3nobi

Getting nginx: [emerg] "upstream" directive is not allowed here in /etc/nginx/sites-enabled/<mysitefile>:25 with this config. I am putting the new stuff inside the server block of my site so maybe that's the issue?

Are you maybe available on Discord to help me troubleshoot this?

0bi-w6n-K3nobi commented 3 years ago

Yeah.... So sorry about this. I'm not use Ubuntu.

In this Doc it says it must be into HTTP block. The Nginx block structure can be seen here.

I believe that you can declare "upstream" into nginx.conf, inside http { block. Try this and give me feedback.

globalistas commented 3 years ago

Well now it's complaining about location directive not allowed....

Man, this is getting too complicated for my taste. I guess I'd better just learn ip tables and be done with this story, lol. Unless you wanna reach on Discord so I don't have to embarass myself here any longer. :D

0bi-w6n-K3nobi commented 3 years ago

Oh, man.... is being so hard for you. So sorry for that.

upstream and map at http { block into nginx.conf and location /wss together with your location /report.html at sites-enabled/<mysitefile>

Now, it will work!

globalistas commented 3 years ago

So the realtime output is not working.

I am using the following command to run GA:

goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED --real-time-html --geoip-database=/home/myuser/city.mmdb --ignore-crawlers --ignore-panel=REQUESTS_STATIC --ignore-panel=STATUS_CODES --ignore-panel=NOT_FOUND --ignore-panel=GEO_LOCATION --origin=http://myvps.domain --ws-url=http://myvps.domain/wss --addr=127.0.0.1 --daemonize

And have this in my site config:

 ##  GoAccess at --ws-url

    location /wss/ {
    allow myIPaddress;
    deny all;

    proxy_pass         http://ga_ws;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Connection $connection_upgrade;
    proxy_buffering    off;
    proxy_read_timeout 7d;
    proxy_set_header   Host $host;
    }

    location /report.html {
        alias /var/www/html/report.html;
        allow myIPaddress;
        deny all;
    }
.
.
.

And this in my nginx config:

http {
        ##  GoAccess at --addr and --port
        upstream ga_ws {
        server 127.0.0.1:7890;
        }

        map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
        }
.
.
.

Any ideas?

0bi-w6n-K3nobi commented 3 years ago

Oh, man... I laughing to myself.

So... Wait, breathe deeply. The correct is --ws-url=wss://myvps.domain/wss and NOT --ws-url=http://myvps.domain/wss Do you can see?

Until next post.

0bi-w6n-K3nobi commented 3 years ago

Humm... Do you using http://myvps.domain or httpS://myvps.domain? If http than use ws:// otherwise if httpS than use wsS://

globalistas commented 3 years ago

OK, trying this on my test server and still no realtime output: goaccess /var/log/nginx/access.log -o /var/www/html/report.html --log-format=COMBINED --real-time-html --ignore-panel=REQUESTS_STATIC --ignore-panel=STATUS_CODES --ignore-panel=NOT_FOUND --ignore-panel=GEO_LOCATION --origin=http://192.168.0.82 --ws-url=ws://192.168.0.82/wss --addr=127.0.0.1

0bi-w6n-K3nobi commented 3 years ago

Strange... must be worked. Do you verify GoAcess binding inside your VPS? You can use for that:

netstat -nat | grep 7890 or netstat -nat | grep 127.0.0.1

globalistas commented 3 years ago
root@devni:~# netstat -nat | grep 7890
tcp        0      0 127.0.0.1:7890          0.0.0.0:*               LISTEN
0bi-w6n-K3nobi commented 3 years ago

... Let's go again... Maybe try again append slash: --ws-url=ws://192.168.0.82/wss/

globalistas commented 3 years ago

Well, it was the slash all along! Now, it works, many thanks man!

0bi-w6n-K3nobi commented 3 years ago

Hi @globalistas

Good morning. I am very happy if I could help.

Slash was my fault. NGinX is sometimes very ticklish.

Well ... Now you can have some idea of what life is like as a system administrator. Many things to guess, a good nose for solving situations.

Welcome. And make good use of GoAccess.

allinurl commented 3 years ago

Glad that worked for you @globalistas.

Thanks a lot @0bi-w6n-K3nobi for providing that help!