Nginx websocket proxy for Node.js - node.js

I am trying to use Node.js to read phoenix channels using npm package phoenix-channels. Phoenix channels are multiplexed on top of websockets. I'm using an NGINX proxy in front of my phoenix webserver, so for NGINX, it's just a websocket.
Phoenix channels work fine going to a web page, as you can see here (you'll see data coming through in the web page).
It also works fine from nodejs on my internal network:
test_chan.js (with explicit IP and port):
const { Socket } = require('phoenix-channels')
let socket = new Socket("https://192.168.1.113:4445/socket")
socket.connect()
// Now that you are connected, you can join channels with a topic:
let channel = socket.channel("room:lobby", {})
channel.on("new_msg", payload => {
console.log(`${payload.body}`);
});
channel.join()
.receive("ok", resp => { console.log("Joined successfully", resp) })
.receive("error", resp => { console.log("Unable to join", resp) })
However if I replace the explicity IP:PORT address with the domain name, and run it from externally, it doesn't work (the only difference here from the script above is the URL):
test_chan.js (through domain name, and via my NGINX proxy):
const { Socket } = require('phoenix-channels')
let socket = new Socket("https://suprabonds.com/socket")
socket.connect()
// Now that you are connected, you can join channels with a topic:
let channel = socket.channel("room:lobby", {})
channel.on("new_msg", payload => {
console.log(`${payload.body}`);
});
channel.join()
.receive("ok", resp => { console.log("Joined successfully", resp) })
.receive("error", resp => { console.log("Unable to join", resp) })
So the suprabonds.com websockets works fine in a browser through the proxy, but doesn't work as a nodejs script.
Here is my nginx conf for suprabonds.com:
sites-enabled relevant server section:
server {
server_name suprabonds.com www.suprabonds.com;
location / {
proxy_pass http://localhost:4445;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/suprabonds.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/suprabonds.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
Any idea as to what I'm doing wrong?
EDIT
Here are the /var/log/nginx/access.log latest entries:
86.143.74.170 - - [22/Apr/2021:15:52:56 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
86.143.74.170 - - [22/Apr/2021:15:52:58 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
86.143.74.170 - - [22/Apr/2021:15:53:03 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
86.143.74.170 - - [22/Apr/2021:15:53:08 +0000] "GET /phoenix/live_reload/socket/websocket?vsn=2.0.0 HTTP/1.1" 101 143 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"
86.143.74.170 - - [22/Apr/2021:15:53:08 +0000] "GET /socket/websocket?token=undefined&vsn=2.0.0 HTTP/1.1" 101 113098 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"
86.143.74.170 - - [22/Apr/2021:15:53:19 +0000] "GET /phoenix/live_reload/socket/websocket?vsn=2.0.0 HTTP/1.1" 101 79 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"
86.143.74.170 - - [22/Apr/2021:15:53:19 +0000] "GET /socket/websocket?token=undefined&vsn=2.0.0 HTTP/1.1" 101 27025 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"
86.143.74.170 - - [22/Apr/2021:15:53:20 +0000] "GET /socket/websocket?token=undefined&vsn=2.0.0 HTTP/1.1" 101 479 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"
86.143.74.170 - - [22/Apr/2021:15:53:20 +0000] "GET /phoenix/live_reload/socket/websocket?vsn=2.0.0 HTTP/1.1" 101 79 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"
86.143.74.170 - - [22/Apr/2021:15:53:23 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
86.143.74.170 - - [22/Apr/2021:15:53:24 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
86.143.74.170 - - [22/Apr/2021:15:53:26 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
86.143.74.170 - - [22/Apr/2021:15:53:31 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
86.143.74.170 - - [22/Apr/2021:15:53:41 +0000] "GET /socket/websocket?vsn=1.0.0 HTTP/1.1" 301 178 "-" "-"
The firefox ones are the ones that work fine. The others (with 301 178 in them) are the ones from the non-working Node.js script (that is, the one using the domain name). The error.log file in the same location is empty.
Please note that I'm also using noip dynamic dns.

If you change your URL to:
let socket = new Socket("wss://suprabonds.com/socket/websocket?token=undefined")
or
let socket = new Socket("wss://suprabonds.com/socket/websocket?vsn=1.0.0")
It will connect

Related

Gunicorn access log format not apply

I'm using gunicorn to run a fastapi script, the access log file were created using the gunicorn.conf.py with accesslog yet it will not apply the access_log_format. I tried this apply this example from the github and is still not working
My gunicorn.conf.py
accesslog = '/home/ossbod/chunhueitest/supervisor_log/accesslog.log'
loglevel = 'info'
access_log_format = '%(h)s %(l)s %(t)s "%(r)s" %(s)s %(q)s %(b)s "%(f)s" "%(a)s" %(M)s'
The result I got
<IP>:54668 - "GET /docs HTTP/1.1" 200
<IP>:54668 - "GET /openapi.json HTTP/1.1" 200
<IP>:54668 - "POST /api/v1/add_user HTTP/1.1" 201
How can i get the format to apply to the log?

I am unable to successfully use my css file in my django project

[03/May/2021 11:44:59] "GET /add_food/ HTTP/1.1" 200 4583
[03/May/2021 11:44:59] "GET /static/css/base.css HTTP/1.1" 404 1763
[03/May/2021 11:45:04] "GET / HTTP/1.1" 200 3812
[03/May/2021 11:45:04] "GET /static/css/base.css HTTP/1.1" 404 1763
[03/May/2021 11:46:24] "GET / HTTP/1.1" 200 3812
[03/May/2021 11:46:24] "GET /static/css/base.css HTTP/1.1" 404 1763
[03/May/2021 11:48:07] "GET / HTTP/1.1" 200 3812
[03/May/2021 11:48:07] "GET /static/css/base.css HTTP/1.1" 404 1763
This is the error I am facing on running the server and reloading the localhost.
the part where I have added my static file is as follows
<link href="{% static 'css/base.css' %}" rel="stylesheet">
where i have defined static in settings.py is as follows:
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_ROOT = os.path.join(BASE_DIR, 'static_saved')
my project structure is linked here
what am i doing wrong?

How can I specify the exact http method with python requests?

In Burp Suite the first line of a captured request is usually GET / HTTP/1.1. However, I am currently practicing Host Header injection using the method of supplying an absolute URL in order to something like this:
GET https://vulnerable-website.com/ HTTP/1.1
Host: bad-stuff-here
In python I am using the requests library and am unable to specify the exact GET request I need.
import requests
burp0_url = "https://vulnerable-website.com:443/"
burp0_cookies = {[redacted]}
burp0_headers = {"Host": "bad-stuff-here", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Referer": "https://vulnerable-website.com/", "Connection": "close", "Upgrade-Insecure-Requests": "1"}
output = requests.get(burp0_url, headers=burp0_headers, cookies=burp0_cookies)
print(output, output.text)
I have tried specifying the GET request in the header dictionary (header = {"GET":" / HTTP/1.1", ...}), however this only results in a GET Header not r
Request on the 6th line being sent:
GET / HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept-Encoding: gzip, deflate
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Connection: close
GET: /
Host: bad-stuff-here
Accept-Language: en-US,en;q=0.5
Referer: https://vulnerable-website.com/
Upgrade-Insecure-Requests: 1
Cookie: [redacted]
This is a very specific problem and I'm not sure if anyone has had the same issues but any help is appreciated. Maybe a workaround with urllib or something I'm missing. Thanks.
requests uses urllib3 under the hood.
You have to craft the request yourself because of non of the clients [urlib, requests, http.client] won't allow you to insert a control character by design.
You can use a plain socket for this
msg = 'GET / HTTP/1.1\r\n\r\n'
s = socket.create_connection(("vulnerable-website.com", 80))
with closing(s):
s.send(msg)
buf = ''.join(iter(partial(s.recv, 4096), ''))

Grok filter for log4js

Iam trying to create a grok logstash filter for my log4js log.
The code in my nodejs app is as follows:
var httpLogFormat = ':remote-addr - - [:date] ":method :url ' + 'HTTP/:http-version" :status :res[content-length] ' + '":referrer" ":user-agent" :response-time';
log4js.loadAppender('file');
log4js.addAppender(log4js.appenders.file('logs/access.log'), 'access');
var logger = log4js.getLogger('access');
app.use(log4js.connectLogger(logger, { level: 'auto', format: httpLogFormat }));
This results in the following log message:
[2017-01-31 08:54:32.491] [WARN] access - 192.1.1.10 - - [Tue, 31 Jan 2017 07:54:32 GMT] "GET /api/test HTTP/1.0" 304 undefined "https://localhost.com/test" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36" 111
My current grok filter looks like this (UPDATED):
grok {
match => { "message" => "\[%{HTTPDATE:timestamp}\] \[%{WORD:loglevel}\] %{WORD:logtype} - %{IPORHOST:clientip} %{USER:ident} %{USER:auth} \"%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})\" %{NUMBER:response} - \"%{DATA:rawrequest}\" \"%{QS:agent}\""}
}
There is some parsing errors, and i suspect it is due to the [] but i'am unsure.
http://grokconstructor.appspot.com/ fails with:
NOT MATCHED. The longest regex prefix matching the beginning of this line is as follows:
prefix "
before match: [2017-01-31 08:54:32.491] [WARN] access - 192.1.1.10 - - [Tue, 31 Jan 2017 07:54:32 GMT]
after match: GET /api/test HTTP/1.0" 304 undefined "https://test.localhost.com/test" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36" 111
I've updated the grok to work for your example. I think you were misusing a few of the types (QS for example you don't need to have the "'s around it):
\[%{GREEDYDATA:timestamp}\]\ \[%{WORD:loglevel}\]\ %{WORD:logtype}\ -\ %{IPORHOST:clientip}\ %{USER:ident}\ %{USER:auth}\ \[%{GREEDYDATA}\]\ \"%{WORD:verb}\ %{NOTSPACE:request}(?: HTTP\/%{NUMBER:httpversion}|)\"\ %{NUMBER:response}\ %{WORD}\ \"%{DATA:rawrequest}\"\ %{QS:agent}\ %{INT:time_taken}
Check the docs for other words you can use.
Your parsing issues are probably down to literal use of the [ and ] characters as they are used in regex's, they need to be escaped as in my example.

nginx default virtual host overrides all

hopefully someone can help, i've been trying to set up nginx with virtual hosts but the default host always overrides any of the others that i specify.
here is my config file found in /etc/nginx/sites-enabled
server {
listen 80;
server_name sub.example.com;
return 404;
}
server {
listen 80 default;
server_name *.example.com;
return 501;
}
and the access.log shows
*.*.*.* - - [30/Oct/2013:04:09:11 +0400] "GET / HTTP/1.1" 501 582 "http://sub.example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36"
*.*.*.* - - [30/Oct/2013:04:09:14 +0400] "GET / HTTP/1.1" 501 582 "http://www.example.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36"
thanks in advance for any help / ideas.
Ant

Resources