Skip to content

Please help? Cryptpad behind Apache reverse proxy hanging at login page with error in browser console #130

@dohlin

Description

@dohlin

Hey guys, I'm really hoping someone a little wiser than me can help me out here, because I'm truly stumped.

I recently set up a fresh cryptpad instance, running on what we'll call "server B" on my internal LAN. A separate server (we'll call this one "server A") is my "main" webserver that either serves requests or acts as a proxy server to redirect http requests to https and then forward those requests to other respective internal servers as needed. The latter is what I'm wanting to do in this case.

If I access Cryptpad via [cryptpad server internal ip]:3000, everything works great. However, if I access it from the outside via the URL I have set up for it, then after attempting to log in it fails with an error message saying "WebSocket connection to 'wss://[my domain here]/cryptpad_websocket' failed: Error during WebSocket handshake: Unexpected response code: 303"

I'm thinking this has got to be something with either my corresponding Apache virtual host file on my main webserver (server 'A') and/or my config.js on my cryptpad server, but despite trying to understand everything that it's doing, adding additional proxypass directives for wss://, tweaking the config.js file, trying different browsers, trying to understand the CSP's more thoroughly, Google'ing for similar issues, etc. I've gotten nowhere in 3 hours of banging my head against the wall lol :)

Here is the full error I'm seeing in the browser console, I'm far from an expert but I'm assuming this might be helpful:

Request URL:wss://[subdomain.example.com]/cryptpad_websocket
Request Method:GET
Status Code:303 See Other
Response Headers
view source
Content-Length:71
Content-Security-Policy:default-src 'none'; style-src 'unsafe-inline' 'self'; script-src 'self'; font-src 'self'; 
child-src 'self' [subdomain.example.com]; connect-src 'self' wss: [subdomain.example.com]; img-src 'self' 
data: blob:
Content-Type:text/html; charset=utf-8
Date:Thu, 01 Jun 2017 05:40:38 GMT
Location:/cryptpad_websocket/
Server:Apache
Strict-Transport-Security:max-age=63072000; includeSubDomains; preload
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
X-Frame-Options:SAMEORIGIN
X-Powered-By:Express
Request Headers
view source
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8
Cache-Control:no-cache
Connection:Upgrade
Host:[subdomain.example.com]
Origin:https://[subdomain.example.com]
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:44Vjjznoyr1lvsvW2TJc0Q==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/58.0.3029.110 Safari/537.36

Can anyone here offer any advice on roughly what things my apache virtual host file would need to include, and what settings I should change in the config.js file for cryptpad? I'll include my current virtualhost file and config.js file down below with personal info redacted for reference of where I'm currently at. I'd be very grateful for any pointers!! Thank you!

Current Apache virtual host file:

 <IfModule mod_ssl.c>

 <VirtualHost *:443>


ServerName [subdomain.example.com]
ServerAdmin webmaster@localhost


SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/[subdomain.example.com]-0002/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/[subdomain.example.com]-0002/privkey.pem


ProxyRequests Off
ProxyPreserveHost On
<Location />
    	ProxyPass http://192.168.1.39:3000/
   	 ProxyPassReverse http://192.168.1.39:3000/
</Location>

 #removed these as they didn't change anything
 #ProxyPass /cryptpad_websocket wss://192.168.1.39:3000/cryptpad_websocket/
 #ProxyPassReverse /cryptpad_websocket wss://192.168.1.39:3000/cryptpad_websocket/


ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined


</VirtualHost>

#vim: syntax=apache ts=4 sw=4 sts=4 sr noet

</IfModule>

Current config.js file:

/@flow/
/*
globals module
*/
module.exports = {

// the address you want to bind to, :: means all ipv4 and ipv6 addresses
// this may not work on all operating systems
httpAddress: '::',

// the port on which your httpd will listen

/*  Cryptpad can be configured to send customized HTTP Headers
 *  These settings may vary widely depending on your needs
 *  Examples are provided below
 */

httpHeaders: {
    "X-XSS-Protection": "1; mode=block",
    "X-Content-Type-Options": "nosniff",
    // 'X-Frame-Options': 'SAMEORIGIN',
},

contentSecurity: [
    "default-src 'none'",
    "style-src 'unsafe-inline' 'self'",
    "script-src 'self'",
    "font-src 'self'",

    /*  child-src is used to restrict iframes to a set of allowed domains.
     *  connect-src is used to restrict what domains can connect to the websocket.
     *
     *  it is recommended that you configure these fields to match the
     *  domain which will serve your cryptpad instance.
     */
    "child-src 'self' [subdomain.example.com]",

    /*  this allows connections over secure or insecure websockets
        if you are deploying to production, you'll probably want to remove
        the ws://* directive, and change '*' to your domain
     */
    "connect-src 'self' wss: [subdomain.example.com]",

    // data: is used by codemirror
    "img-src 'self' data: blob:",
].join('; '),

// CKEditor requires significantly more lax content security policy in order to function.
padContentSecurity: [
    "default-src 'none'",
    "style-src 'unsafe-inline' 'self'",
    // Unsafe inline, unsafe-eval are needed for ckeditor :(
    "script-src 'self' 'unsafe-eval' 'unsafe-inline'",
    "font-src 'self'",

    /*  See above under 'contentSecurity' as to how these values should be
     *  configured for best effect.
     */
     "child-src 'self' [subdomain.example.com]",

    // see the comment above in the 'contentSecurity' section
     "connect-src 'self' wss: [subdomain.example.com]",

    // (insecure remote) images are included by users of the wysiwyg who embed photos in their pads
    "img-src *",
].join('; '),

httpPort: 3000,

/*  your server's websocket url is configurable
 *  (default: '/cryptpad_websocket')
 *
 *  websocketPath can be relative, of the form '/path/to/websocket'
 *  or absolute, specifying a particular URL
 *
 *  'wss://cryptpad.fr:3000/cryptpad_websocket'
 */
websocketPath: '/cryptpad_websocket',

/*  it is assumed that your websocket will bind to the same port as http
 *  you can override this behaviour by supplying a number via websocketPort
 */
//websocketPort: 3000,

/*  if you want to run a different version of cryptpad but using the same websocket
 *  server, you should use the other server port as websocketPort and disable
 *  the websockets on that server
 */
//useExternalWebsocket: false,

/*  If Cryptpad is proxied without using https, the server needs to know.
 *  Specify 'useSecureWebsockets: true' so that it can send
 *  Content Security Policy Headers that prevent http and https from mixing
 */
 useSecureWebsockets: true,

/*  Cryptpad can log activity to stdout
 *  This may be useful for debugging
 */
logToStdout: false,

/*  Cryptpad supports verbose logging
 *  (false by default)
 */
 verbose: false,

/*  Main pages
 *  add exceptions to the router so that we can access /privacy.html
 *  and other odd pages
 */
mainPages: [
    'index',
    'privacy',
    'terms',
    'about',
    'contact',
],

/*  Domain
 *  If you want to have enable payments on your CryptPad instance, it has to be able to tell
 *  our account server what is your domain
 */
// domain: 'https://cryptpad.fr',

/*
    You have the option of specifying an alternative storage adaptor.
    These status of these alternatives are specified in their READMEs,
    which are available at the following URLs:

    mongodb: a noSQL database
        https://github.com/xwiki-labs/cryptpad-mongo-store
    amnesiadb: in memory storage
        https://github.com/xwiki-labs/cryptpad-amnesia-store
    leveldb: a simple, fast, key-value store
        https://github.com/xwiki-labs/cryptpad-level-store
    sql: an adaptor for a variety of sql databases via knexjs
        https://github.com/xwiki-labs/cryptpad-sql-store

    For the most up to date solution, use the default storage adaptor.
*/
storage: './storage/file',

/*
    Cryptpad stores each document in an individual file on your hard drive.
    Specify a directory where files should be stored.
    It will be created automatically if it does not already exist.
*/
filePath: './datastore/',

/*  CryptPad allows logged in users to request that particular documents be
 *  stored by the server indefinitely. This is called 'pinning'.
 *  Pin requests are stored in a pin-store. The location of this store is
 *  defined here.
 */
pinPath: './pins',

/*  CryptPad allows logged in users to upload encrypted files. Files/blobs
 *  are stored in a 'blob-store'. Set its location here.
 */
blobPath: './blob',

/*  CryptPad stores incomplete blobs in a 'staging' area until they are
 *  fully uploaded. Set its location here.
 */
blobStagingPath: './blobstage',

/*  Cryptpad's file storage adaptor closes unused files after a configurale
 *  number of milliseconds (default 30000 (30 seconds))
 */
channelExpirationMs: 30000,

/*  Cryptpad's file storage adaptor is limited by the number of open files.
 *  When the adaptor reaches openFileLimit, it will clean up older files
 */
openFileLimit: 2048,

/*  Cryptpad's socket server can be extended to respond to RPC calls
 *  you can configure it to respond to custom RPC calls if you like.
 *  provide the path to your RPC module here, or `false` if you would
 *  like to disable the RPC interface completely
 */
rpc: './rpc.js',

/*  RPC errors are shown by default, but if you really don't care,
 *  you can suppress them
 */
suppressRPCErrors: false,


/* WARNING: EXPERIMENTAL
 *
 *  CryptPad features experimental support for encrypted file upload.
 *  Our encryption format is still liable to change. As such, we do not
 *  guarantee that files uploaded now will be supported in the future
 */

/*  Setting this value to anything other than true will cause file upload
 *  attempts to be rejected outright.
 */
enableUploads: false,

/*  If you have enabled file upload, you have the option of restricting it
 *  to a list of users identified by their public keys. If this value is set
 *  to true, your server will query a file (cryptpad/privileged.conf) when
 *  users connect via RPC. Only users whose public keys can be found within
 *  the file will be allowed to upload.
 *
 *  privileged.conf uses '#' for line comments, and splits keys by newline.
 *  This is a temporary measure until a better quota system is in place.
 *  registered users' public keys can be found on the settings page.
 */
//restrictUploads: false,

/*  Default user storage limit (bytes)
 *  if you don't want to limit users,
 *  you can set this to the size of your hard disk
 */
defaultStorageLimit: 50 * 1024 * 1024,

/*  Max Upload Size (bytes)
 *  this sets the maximum size of any one file uploaded to the server.
 *  anything larger than this size will be rejected
 */
maxUploadSize: 20 * 1024 * 1024,

/*  clients can use the /settings/ app to opt out of usage feedback
 *  which informs the server of things like how much each app is being
 *  used, and whether certain clientside features are supported by
 *  the client's browser. The intent is to provide feedback to the admin
 *  such that the service can be improved. Enable this with `true`
 *  and ignore feedback with `false` or by commenting the attribute
 */
//logFeedback: true,

/* it is recommended that you serve cryptpad over https
 * the filepaths below are used to configure your certificates
 */
//privKeyAndCertFiles: [
//  '/etc/apache2/ssl/my_secret.key',
//  '/etc/apache2/ssl/my_public_cert.crt',
//  '/etc/apache2/ssl/my_certificate_authorities_cert_chain.ca'
//],
};

EDIT: I think I finally got it many hours of headaches later!! I'll close this issue myself now, but in case anyone finds themselves with similar issues, here's how I fixed mine:

All I needed to do what add the following lines to my Apache virtual host file:

RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* ws://[insert cryptpad server internal ip]:3000%{REQUEST_URI} [P]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions