CoralReactor implements its own non-blocking SSLSocketChannel
so you can have out-of-box support for SSL. In this article we show how you can connect to a SSL server (https, wss, etc.) easily with a CoralReactor client.
A Simple HTTP Client
For plain-text HTTP port 80 it is extremely easy. For example, to connect to www.google.com and fetch the HTTP response headers you can write the simple cliente below:
package com.coralblocks.coralreactor.client.ssl; import static com.coralblocks.corallog.Log.*; import java.net.URL; import java.nio.ByteBuffer; import com.coralblocks.coralbits.util.ByteBufferUtils; import com.coralblocks.coralreactor.client.AbstractLineTcpClient; import com.coralblocks.coralreactor.client.Client; import com.coralblocks.coralreactor.nio.NioReactor; public class SSLClient extends AbstractLineTcpClient { public SSLClient(NioReactor nio, String host, int port) { super(nio, host, port); } @Override protected void handleConnectionOpened() { send("GET / HTTP/1.0\n"); } @Override protected void handleMessage(ByteBuffer msg) { // only print the HTTP response headers String s = ByteBufferUtils.parseString(msg); if (s.startsWith("<")) { close(); } else { System.out.println(s); } } public static void main(String[] args) throws Exception { URL url = new URL("http://www.google.com"); // note we are using HTTP (port 80) String proto = url.getProtocol(); String host = url.getHost(); int port = url.getDefaultPort(); NioReactor nio = NioReactor.create(); Info.log("Connecting...", "url=", url, "host=", host, "port=", port, "proto=", proto); final Client client = new SSLClient(nio, host, port); client.open(); nio.start(); } }
And the output:
22:13:40.350783-INFO Connecting... url=http://www.google.com host=www.google.com port=80 proto=http 22:13:40.372449-INFO SSLClient-www.google.com:80 Client opened! sequence=1 session=null 22:13:40.390583-INFO NioReactor Reactor started! type=OptimumNioReactor impl=KQueueSelectorImpl 22:13:40.595306-INFO SSLClient-www.google.com:80 Connection established! 22:13:40.595489-INFO SSLClient-www.google.com:80 Connection opened! HTTP/1.0 200 OK Date: Thu, 10 Sep 2015 02:13:40 GMT Expires: -1 Cache-Control: private, max-age=0 Content-Type: text/html; charset=ISO-8859-1 P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." Server: gws X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN Set-Cookie: PREF=ID=1111111111111111:FF=0:TM=1441851220:LM=1441851220:V=1:S=XSWC8Y8PJthovQv9; expires=Thu, 31-Dec-2015 16:02:17 GMT; path=/; domain=.google.com Set-Cookie: NID=71=uGm6eP_jn9OmofaZ4RX10EFlALI8NmfX9jnfSiLrNlWPngHQdR1q_pl2QifvtlJJBmPi6_Dmoacg8pP2A8TgifnQ7EIxQAOoR15DkRohQrBUKn1nFauUkoUwSwgIKgPv; expires=Fri, 11-Mar-2016 02:13:40 GMT; path=/; domain=.google.com; HttpOnly Accept-Ranges: none Vary: Accept-Encoding 22:13:40.839168-INFO SSLClient-www.google.com:80 Client was shutdown 22:13:40.839329-INFO SSLClient-www.google.com:80 Client closed!
Switching to HTTPS
CoralReactor will automatically connect to the server to download and install the required SSL certificates so that you don’t have to worry about anything to make SSL work. All you have to do is turn it on with a config parameter (i.e. useSSL) and pass the appropriate SSL port (i.e. 443) to you client:
public static void main(String[] args) throws Exception { URL url = new URL("https://www.google.com"); // note we are using HTTPS now (port 443) String proto = url.getProtocol(); String host = url.getHost(); int port = url.getDefaultPort(); NioReactor nio = NioReactor.create(); MapConfiguration config = new MapConfiguration(); config.add("useSSL", true); // tell CoralReactor that we want to use SSL Info.log("Connecting...", "url=", url, "host=", host, "port=", port, "proto=", proto); final Client client = new SSLClient(nio, host, port, config); client.open(); nio.start(); }
And the output:
22:51:00.100277-INFO Connecting... url=https://www.google.com host=www.google.com port=443 proto=https 22:51:00.118394-INFO SSLClient-www.google.com:443 Client opened! sequence=1 session=null 22:51:00.880822-INFO NioReactor Reactor started! type=OptimumNioReactor impl=KQueueSelectorImpl 22:51:01.055298-INFO SSLClient-www.google.com:443 Connection established! 22:51:01.055608-INFO SSLClient-www.google.com:443 Connection opened! HTTP/1.0 200 OK Date: Thu, 10 Sep 2015 02:51:01 GMT Expires: -1 Cache-Control: private, max-age=0 Content-Type: text/html; charset=ISO-8859-1 P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." Server: gws X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN Set-Cookie: PREF=ID=1111111111111111:FF=0:TM=1441853461:LM=1441853461:V=1:S=W287StjqyNrsY-rC; expires=Thu, 31-Dec-2015 16:02:17 GMT; path=/; domain=.google.com Set-Cookie: NID=71=Z-T634Zo9qGSn9GbdTlmX5KFeU6ZZrzVySqrtfJWuD_nwFbo8Qlsm3EzeRCgiybqBmnW7Mkmn0IdGTVgv6nMaUrX3YtvfsRzQH-FgmJAzGpVv1y9WV2DaLa3UNPgY1uY; expires=Fri, 11-Mar-2016 02:51:01 GMT; path=/; domain=.google.com; HttpOnly Alternate-Protocol: 443:quic,p=1 Alt-Svc: quic=":443"; p="1"; ma=604800 Accept-Ranges: none Vary: Accept-Encoding 22:51:01.283551-INFO SSLClient-www.google.com:443 Client was shutdown 22:51:01.283760-INFO SSLClient-www.google.com:443 Client closed!
More Control (only if you need to)
CoralReactor uses javax.net.ssl.SSLEngine
under the hood as specified here to implement its SSL support and encrypt the socket communication. If you want more control you can download and install the SSL certificates yourself (i.e. manually) and tell CoralReactor where to find them. These can be done with openssl and keytool.
For example to download the certificate from google you can do:
$ echo "" | openssl s_client -connect www.google.com:443 -showcerts 2>/dev/null | openssl x509 -out google.cer
To add the google.cer you downloaded above to a keystore so it can be passed to a CoralReactor client you can do:
$ keytool -import -file google.cer -alias google -keystore google.jks -storepass "abc123" -keypass "abc123"
Now you can inform the CoralReactor client that you want to use the google.jks keystore. See below:
public static void main(String[] args) throws Exception { URL url = new URL("https://www.google.com"); // note we are using HTTPS now String proto = url.getProtocol(); String host = url.getHost(); int port = url.getDefaultPort(); NioReactor nio = NioReactor.create(); MapConfiguration config = new MapConfiguration(); config.add("useSSL", true); // tell CoralReactor that we want to use SSL config.add("sslKeyStoreFile", "/path/to/google.jks"); // path to keystore file config.add("sslKeyPassword", "abc123"); // key password config.add("sslKeyStorePassword", "abc123"); // keystore password Info.log("Connecting...", "url=", url, "host=", host, "port=", port, "proto=", proto); final Client client = new SSLClient(nio, host, port, config); client.open(); nio.start(); }
Using Stunnel as a SSL Proxy
For a cleaner alternative you can also use stunnel as a SSL proxy. For example to connect to google.com:443 use the stunnel.conf file below:
[remote] client = yes accept = 8888 connect = www.google.com:443
Then run stunnel:
$ sudo stunnel stunnel.conf
You can easily test with netcat with the command-line below:
$ cat <(echo -e "GET / HTTP/1.0\n") | nc localhost 8888 | head -n 9 HTTP/1.0 200 OK Date: Thu, 10 Sep 2015 03:09:13 GMT Expires: -1 Cache-Control: private, max-age=0 Content-Type: text/html; charset=ISO-8859-1 P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." Server: gws X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN