问题
General scheme and project configuration files
The project consists of two parts:
- Server part - Laravel (api)
- Customer part - NuxtJs (client)
A minimum project configuration has been prepared for the test:
Laravel
Websockets packages have been installed:
- beyondcode/laravel-websockets: https://beyondco.de/docs/laravel-websockets/getting-started/introduction
- pusher/pusher-php-server: https://pusher.com/tutorials/web-notifications-laravel-pusher-channels
File composer.json:
...
"require": {
"php": "^7.3",
"beyondcode/laravel-websockets": "^1.8",
"fideloper/proxy": "^4.2",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^8.0",
"laravel/tinker": "^2.0",
"pusher/pusher-php-server": "^4.1"
},
"require-dev": {
"facade/ignition": "^2.3.6",
"fzaninotto/faker": "^1.9.1",
"mockery/mockery": "^1.3.1",
"nunomaduro/collision": "^5.0",
"phpunit/phpunit": "^9.3"
},
...
Nuxt
Websockets packages have been installed:
- nuxtjs/laravel-echo: https://github.com/nuxt-community/laravel-echo
- pusher-js: https://github.com/pusher/pusher-js
File package.json:
...
"dependencies": {
"@nuxtjs/axios": "^5.12.2",
"@nuxtjs/dotenv": "^1.4.1",
"@nuxtjs/laravel-echo": "^1.1.0",
"@nuxtjs/proxy": "^2.0.1",
"nuxt": "^2.13.0",
"pusher-js": "^7.0.0"
},
...
All files have already been uploaded to VPS (Ubuntu 18.04 LTS) and a certificate has been obtained (https://certbot.eff.org/):
root@dsde1032-21892:/var/www# ls
api client html
The websockets server has been launched on a permanent basis under this description: https://beyondco.de/docs/laravel-websockets/basic-usage/starting
supervisorctl status
root@dsde1032-21892:/var/www# supervisorctl status
websockets RUNNING pid 1421, uptime 1:16:50
A process manager has been installed and launched globally to automatically start and reload the customer part: https://pm2.keymetrics.io
pm2 list
root@dsde1032-21892:/var/www# pm2 list
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name │ mode │ * │ status │ cpu │ memory │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 0 │ larastart │ fork │ 263… │ online │ 0% │ 52.8mb │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
List of occupied ports:
netstat -ntlp | grep LISTEN
root@dsde1032-21892:/var/www# netstat -ntlp | grep LISTEN
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 968/mysqld
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 961/nginx: master p
tcp 0 0 0.0.0.0:6001 0.0.0.0:* LISTEN 1421/php
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 945/sshd
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN 12821/node
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 961/nginx: master p
tcp6 0 0 :::22 :::* LISTEN 945/sshd
lsof -i -P -n | grep LISTEN
root@dsde1032-21892:/var/www# lsof -i -P -n | grep LISTEN
sshd 945 root 3u IPv4 19310 0t0 TCP *:22 (LISTEN)
sshd 945 root 4u IPv6 19314 0t0 TCP *:22 (LISTEN)
nginx 961 root 6u IPv4 19430 0t0 TCP *:80 (LISTEN)
nginx 961 root 10u IPv4 554283 0t0 TCP *:443 (LISTEN)
mysqld 968 mysql 31u IPv4 19706 0t0 TCP 127.0.0.1:3306 (LISTEN)
php 1421 root 5u IPv4 2352082 0t0 TCP *:6001 (LISTEN)
node 12821 root 18u IPv4 581986 0t0 TCP 127.0.0.1:3000 (LISTEN)
nginx 32555 www-data 6u IPv4 19430 0t0 TCP *:80 (LISTEN)
nginx 32555 www-data 10u IPv4 554283 0t0 TCP *:443 (LISTEN)
Current status of network security:
ufw status
root@dsde1032-21892:/var/www# ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)
The answer from the server part, when requests are made from the client part, comes:
Request URL: https://larastart.site/api/
Request Method: POST
Status Code: 200 OK
Remote Address: 91.228.155.156:443
Referrer Policy: strict-origin-when-cross-origin
An error is generated with websockets:
Request URL: wss://larastart.site:6001/app/456?protocol=7&client=js&version=4.4.0&flash=false
WebSocket is closed before the connection is established.
WebSocket opening handshake timed out
Files for setting up web sockets
Laravel
File .env:
vim /var/www/api/.env
APP_NAME=Laranuxt
APP_ENV=production
APP_KEY=base64:cSTA4y9lIjmQDQ9b3+J2X+iSif8jqu6u3Oj9UNXdzIs=
APP_DEBUG=false
APP_SCHEME=https://
APP_HOST=larastart.site
APP_URL="${APP_SCHEME}larastart.site"
CLIENT_URL="${APP_SCHEME}larastart.site"
...
PUSHER_APP_ID=123
PUSHER_APP_KEY=456
PUSHER_APP_SECRET=789
PUSHER_APP_CLUSTER=test
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
File websockets.php:
vim /var/www/api/config/websockets.php
...
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => true,
'enable_statistics' => false,
],
],
...
File broadcasting.php:
vim /var/www/api/config/broadcasting.php
...
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => false,
'encrypted' => false,
'host' => env('APP_HOST'),
'port' => 6001,
'scheme' => 'http',
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
]
],
],
...
],
...
Nuxt
cd /var/www/client
File .env:
vim /var/www/client/.env
SCHEME = https://
BASE_URL = "${SCHEME}larastart.site"
API_DOMAIN = "${SCHEME}larastart.site"
API_URL = "${SCHEME}larastart.site/api"
BROADCAST_DRIVER = pusher
PUSHER_APP_ID = 123
PUSHER_APP_KEY = 456
PUSHER_APP_SECRET = 789
PUSHER_APP_CLUSTER = test
File echo.js:
vim /var/www/client/plugins/echo.js
import Echo from 'laravel-echo';
export default (app) => {
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: process.env.BROADCAST_DRIVER,
key: process.env.PUSHER_APP_KEY,
cluster: process.env.PUSHER_APP_CLUSTER,
forceTLS: false,
encrypted: false,
wsHost: window.location.hostname,
wsPort: 6001,
wssPort: 6001,
disableStats: false,
enabledTransports: ['ws', 'wss']
});
}
File nuxt.config.js:
vim /var/www/client/nuxt.config.js
...
plugins: [
{ src: '~/plugins/echo.js', ssr: false }
],
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy',
'@nuxtjs/dotenv'
],
axios: {
baseURL: process.env.API_DOMAIN,
credentials: true
},
proxy: {
"/api": {
target: process.env.API_DOMAIN,
pathRewrite: { "^/api" : "/" }
}
},
...
Nginx
A configuration file for the site on the Nginx web server has been created and is connected:
ls /etc/nginx/sites-enabled/
root@dsde1032-21892:/var/www# ls /etc/nginx/sites-enabled/
larastart.site
vim /etc/nginx/sites-available/larastart.site
server {
server_name larastart.site;
root /var/www/api/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
# Priority file extensions
index index.php index.html index.htm index.nginx-debian.html;
charset utf-8;
# Check for the existence of files matching a provided url, forward to 404 if not found
location /api {
try_files $uri $uri/ /index.php?$query_string;
}
# Serve static files directly
location ~* ^/storage/(.*)\.(jpg|jpeg|gif|bmp|png|ico)$ {
access_log off;
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-VerifiedViaNginx yes;
proxy_read_timeout 300;
proxy_connect_timeout 300;
}
location /app {
proxy_pass http://127.0.0.1:6001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-VerifiedViaNginx yes;
proxy_read_timeout 300;
proxy_connect_timeout 300;
# Specific for websockets: force the use of HTTP/1.1 and set the Upgrade header
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
error_page 404 /index.php;
# pass PHP scripts to FastCGI server
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root concurs with nginx's one
location ~ /\.(?!well-known).* {
deny all;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/larastart.site/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/larastart.site/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
}
server {
if ($host = larastart.site) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name larastart.site;
return 404; # managed by Certbot
}
回答1:
The solution has been found. I want to share my settings, which played a key role.
Project settings
Firewall
netstat -ntlp | grep LISTEN
root@dsde1032-21892:~# netstat -ntlp | grep LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1066/nginx: master
tcp 0 0 0.0.0.0:6001 0.0.0.0:* LISTEN 7768/php
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1064/sshd
tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN 1173/node
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 1066/nginx: master
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 1078/mysqld
tcp6 0 0 :::22 :::* LISTEN 1064/sshd
lsof -i -P -n | grep LISTEN
root@dsde1032-21892:~# lsof -i -P -n | grep LISTEN
sshd 1064 root 3u IPv4 20044 0t0 TCP *:22 (LISTEN)
sshd 1064 root 4u IPv6 20138 0t0 TCP *:22 (LISTEN)
nginx 1066 root 6u IPv4 20168 0t0 TCP *:443 (LISTEN)
nginx 1066 root 7u IPv4 20169 0t0 TCP *:80 (LISTEN)
mysqld 1078 mysql 31u IPv4 20463 0t0 TCP 127.0.0.1:3306 (LISTEN)
node 1173 root 18u IPv4 20902 0t0 TCP 127.0.0.1:3000 (LISTEN)
nginx 7402 www-data 6u IPv4 20168 0t0 TCP *:443 (LISTEN)
nginx 7402 www-data 7u IPv4 20169 0t0 TCP *:80 (LISTEN)
php 7768 root 5u IPv4 110549 0t0 TCP *:6001 (LISTEN)
ufw status
root@dsde1032-21892:~# ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
6001 ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)
6001 (v6) ALLOW Anywhere (v6)
ufw show listening
root@dsde1032-21892:~# ufw show listening
tcp:
22 * (sshd)
[ 1] allow OpenSSH
443 * (nginx)
[ 2] allow 'Nginx Full'
6001 * (php7.4)
[ 3] allow 6001
80 * (nginx)
[ 2] allow 'Nginx Full'
tcp6:
22 * (sshd)
[ 4] allow OpenSSH
Laravel
vim /var/www/api/config/websockets.php
...
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => true,
'enable_statistics' => false,
],
],
...
'ssl' => [
'local_cert' => '/etc/letsencrypt/live/larastart.site/fullchain.pem',
'local_pk' => '/etc/letsencrypt/live/larastart.site/privkey.pem',
'passphrase' => null,
'verify_peer' => false
],
...
vim /var/www/api/config/broadcasting.php
...
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
'encrypted' => false,
'host' => '127.0.0.1',
'port' => 6001,
'scheme' => 'https',
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
]
],
],
...
],
...
Nuxt
vim /var/www/client/package.json
{
"name": "frontend",
"version": "1.0.0",
"private": true,
"config": {
"nuxt": {
"port": "3000"
}
},
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"export": "nuxt export",
"serve": "nuxt serve"
},
"dependencies": {
"@nuxtjs/axios": "^5.12.2",
"@nuxtjs/dotenv": "^1.4.1",
"@nuxtjs/laravel-echo": "^1.1.0",
"@nuxtjs/proxy": "^2.0.1",
"nuxt": "^2.13.0",
"pusher-js": "^4.4.0"
},
"devDependencies": {}
}
vim /var/www/client/plugins/echo.js
import Echo from 'laravel-echo';
export default (app) => {
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: process.env.BROADCAST_DRIVER,
key: process.env.PUSHER_APP_KEY,
cluster: process.env.PUSHER_APP_CLUSTER,
forceTLS: true,
encrypted: false,
wsHost: window.location.hostname,
wsPort: 6001,
wssPort: 6001,
disableStats: true,
enabledTransports: ['ws', 'wss']
});
}
Nginx
vim /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
vim /etc/nginx/sites-available/larastart.site
server {
server_name larastart.site;
root /var/www/api/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
# Priority file extensions
index index.php index.html index.htm index.nginx-debian.html;
charset utf-8;
# Check for the existence of files matching a provided url, forward to 404 if not found
location /api {
try_files $uri $uri/ /index.php?$query_string;
}
# Serve static files directly
location ~* ^/storage/(.*)\.(jpg|jpeg|gif|bmp|png|ico)$ {
access_log off;
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-VerifiedViaNginx yes;
proxy_read_timeout 300;
proxy_connect_timeout 300;
}
location /app {
proxy_pass https://larastart.site:6001;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
error_page 404 /index.php;
# pass PHP scripts to FastCGI server
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root concurs with nginx's one
location ~ /\.(?!well-known).* {
deny all;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/larastart.site/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/larastart.site/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
}
server {
if ($host = larastart.site) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name larastart.site;
return 404; # managed by Certbot
}
来源:https://stackoverflow.com/questions/64477776/laravel-nuxt-nginx-websocket-is-closed-before-the-connection-is-established