Enable client certificate verification if ssl CA is given

This commit is contained in:
Shuanglei Tao
2016-11-23 23:19:32 +08:00
parent 06b8074b1e
commit 15e2dd96a4
4 changed files with 46 additions and 9 deletions

View File

@@ -70,10 +70,10 @@ OPTIONS:
--client-option, -t Send option to client (format: key=value), repeat to add more options --client-option, -t Send option to client (format: key=value), repeat to add more options
--check-origin, -O Do not allow websocket connection from different origin --check-origin, -O Do not allow websocket connection from different origin
--once, -o Accept only one client and exit on disconnection --once, -o Accept only one client and exit on disconnection
--ssl, -S Enable ssl --ssl, -S Enable SSL
--ssl-cert, -C Ssl certificate file path --ssl-cert, -C SSL certificate file path
--ssl-key, -K Ssl key file path --ssl-key, -K SSL key file path
--ssl-ca, -A Ssl ca file path --ssl-ca, -A SSL CA file path for client certificate verification
--debug, -d Set log level (0-9, default: 7) --debug, -d Set log level (0-9, default: 7)
--version, -v Print the version and exit --version, -v Print the version and exit
--help, -h Print this text and exit --help, -h Print this text and exit
@@ -94,6 +94,32 @@ Then open <http://localhost:8080> with a broswer, you will get a bash shell with
- You can even run a none shell command like vim, try: `ttyd vim`, the web broswer will show you a vim editor. - You can even run a none shell command like vim, try: `ttyd vim`, the web broswer will show you a vim editor.
- Sharing single process with multiple clients: `ttyd tmux new -A -s ttyd vim`, run `tmux new -A -s ttyd` to connect to the tmux session from terminal. - Sharing single process with multiple clients: `ttyd tmux new -A -s ttyd vim`, run `tmux new -A -s ttyd` to connect to the tmux session from terminal.
## SSL how-to
Generate SSL CA and self signed server/client certificates:
```bash
# CA
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
# server certificate
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
# client certificate (the p12/pem format may be useful for some clients)
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
openssl pkcs12 -in client.p12 -out client.pem -clcerts
```
Then start ttyd:
```bash
ttyd --ssl --ssl-cert ca.crt --ssl-key ca.key --ssl-ca ca.crt bash
```
If you don't want to enable client certificate verification, remove the `--ssl-ca` option.
## Docker and ttyd ## Docker and ttyd
Docker containers are jailed environments which are more secure, this is useful for protecting the host system, you may use ttyd with docker like this: Docker containers are jailed environments which are more secure, this is useful for protecting the host system, you may use ttyd with docker like this:

View File

@@ -127,6 +127,15 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
if (lws_write_http(wsi, index_html, index_html_len) < 0) if (lws_write_http(wsi, index_html, index_html_len) < 0)
return 1; return 1;
goto try_to_reuse; goto try_to_reuse;
case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
if (!len || (SSL_get_verify_result((SSL*)in) != X509_V_OK)) {
int err = X509_STORE_CTX_get_error((X509_STORE_CTX*)user);
int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX*)user);
const char* msg = X509_verify_cert_error_string(err);
lwsl_err("client certificate verification error: %s (%d), depth: %d\n", msg, err, depth);
return 1;
}
break;
default: default:
break; break;
} }

View File

@@ -133,7 +133,7 @@ thread_run_command(void *args) {
pid_t pid = forkpty(&pty, NULL, NULL, NULL); pid_t pid = forkpty(&pty, NULL, NULL, NULL);
switch (pid) { switch (pid) {
case -1: /* */ case -1: /* error */
lwsl_err("forkpty\n"); lwsl_err("forkpty\n");
break; break;
case 0: /* child */ case 0: /* child */

View File

@@ -61,10 +61,10 @@ void print_help() {
" --client-option, -t Send option to client (format: key=value), repeat to add more options\n" " --client-option, -t Send option to client (format: key=value), repeat to add more options\n"
" --check-origin, -O Do not allow websocket connection from different origin\n" " --check-origin, -O Do not allow websocket connection from different origin\n"
" --once, -o Accept only one client and exit on disconnection\n" " --once, -o Accept only one client and exit on disconnection\n"
" --ssl, -S Enable ssl\n" " --ssl, -S Enable SSL\n"
" --ssl-cert, -C Ssl certificate file path\n" " --ssl-cert, -C SSL certificate file path\n"
" --ssl-key, -K Ssl key file path\n" " --ssl-key, -K SSL key file path\n"
" --ssl-ca, -A Ssl ca file path\n" " --ssl-ca, -A SSL CA file path for client certificate verification\n"
" --debug, -d Set log level (0-9, default: 7)\n" " --debug, -d Set log level (0-9, default: 7)\n"
" --version, -v Print the version and exit\n" " --version, -v Print the version and exit\n"
" --help, -h Print this text and exit\n", " --help, -h Print this text and exit\n",
@@ -332,6 +332,8 @@ main(int argc, char **argv) {
"!DHE-RSA-AES256-SHA256:" "!DHE-RSA-AES256-SHA256:"
"!AES256-GCM-SHA384:" "!AES256-GCM-SHA384:"
"!AES256-SHA256"; "!AES256-SHA256";
if (strlen(info.ssl_ca_filepath) > 0)
info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
#if LWS_LIBRARY_VERSION_MAJOR == 2 #if LWS_LIBRARY_VERSION_MAJOR == 2
info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS; info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS;
#endif #endif