0
votes

I'm currently running an apache2 webserver on Ubuntu. This web server is hosting a Vue.js web app that connects to a .Net Core app (also on the same linux server) with SignalR to create a websocket.

The .Net Core app is ran using Kestrel. Below is the apache config to reroute the domain.com/api to the .Net Core app running on port 5000.

<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://www.example.com/
</VirtualHost>

<VirtualHost _default_:443>
DocumentRoot /var/www/example.com/dist/spa
ServerName www.example.com
ServerAlias example.com

ProxyPreserveHost On
ProxyPass "/api" http://localhost:5000/
ProxyPassReverse "/api" http://localhost:5000/
RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
  RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
  RewriteRule /(.*) ws://localhost:5000/$1 [P]

SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
SSLCertificateFile /etc/apache2/ssl/example_com.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
SSLCertificateChainFile /etc/apache2/ssl/example_com.ca-bundle

ErrorLog ${APACHE_LOG_DIR}example-error.log
CustomLog ${APACHE_LOG_DIR}example.log common
</VirtualHost>

When the Vue.js app attempts to create a websocket connection to the example.com/api/mainHub the following error occurs:

Failed to complete negotiation with the server: SyntaxError: Unexpected token H in JSON at position 0

It seems to be sending the request to the correct URL, https://example.com/api/mainHub but fails to establish the connection.

One thing I noticed on the Linux server, is the POST does not include the /api in the path.

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 POST http://example.com//mainHub/negotiate text/plain;charset=UTF-8 0

Is this an issue with how my apache2 config is routing the requests to the /api directory?

Edit I've since changed my apache config to remove the extra / at the end of the localhost:5000 - This allowed the outside connection to reach the correct API path.

<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://www.example.com/
</VirtualHost>

<VirtualHost _default_:443>
DocumentRoot /var/www/example.com/dist/spa
ServerName www.example.com
ServerAlias example.com

RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
  RewriteRule /(.*) wss://localhost:5000$1 [P]
  RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
  RewriteRule /(.*) https://localhost:5000$1 [P]

ProxyPreserveHost On
ProxyPass "/api" http://localhost:5000
ProxyPassReverse "/api" http://localhost:5000

SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
SSLCertificateFile /etc/apache2/ssl/example_com.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
SSLCertificateChainFile /etc/apache2/ssl/example_com.ca-bundle

ErrorLog ${APACHE_LOG_DIR}example-error.log
CustomLog ${APACHE_LOG_DIR}example.log common
</VirtualHost>

The issue now seems to be with the secure websocket upgrade. I tried changing the ws upgrade to wss, but something is still wrong. When the client attempts to make the wss connection, the following error occurs:

WebSocket connection to 'wss://example.com/api/mainHub?id=k1-_KxspgAQgIAhKroQBpQ' failed: Error during WebSocket handshake: Unexpected response code: 502

I believe something is wrong with how my virtual host is upgrading the websocket connection with HTTPS.

Error: Failed to start the transport 'WebSockets': null

1

1 Answers

1
votes

If your .Net Core app is listening at /api/ on port 5000, then add that to ProxyPass directives:

ProxyPass "/api" http://localhost:5000/api
ProxyPassReverse "/api" http://localhost:5000/api

Edit: Try

RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
  RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
  RewriteRule /(.*) ws://localhost:5000/$1 [P]

ProxyPreserveHost On
ProxyPass "/api" http://localhost:5000
ProxyPassReverse "/api" http://localhost:5000