Committed by
Gerrit Code Review
securing the openflow channel
Change-Id: Ifae379e7e372baeb14a4ad919f014c64752c3a7f
Showing
2 changed files
with
95 additions
and
2 deletions
| ... | @@ -39,9 +39,15 @@ import org.projectfloodlight.openflow.protocol.OFVersion; | ... | @@ -39,9 +39,15 @@ import org.projectfloodlight.openflow.protocol.OFVersion; |
| 39 | import org.slf4j.Logger; | 39 | import org.slf4j.Logger; |
| 40 | import org.slf4j.LoggerFactory; | 40 | import org.slf4j.LoggerFactory; |
| 41 | 41 | ||
| 42 | +import javax.net.ssl.KeyManagerFactory; | ||
| 43 | +import javax.net.ssl.SSLContext; | ||
| 44 | +import javax.net.ssl.SSLEngine; | ||
| 45 | +import javax.net.ssl.TrustManagerFactory; | ||
| 46 | +import java.io.FileInputStream; | ||
| 42 | import java.lang.management.ManagementFactory; | 47 | import java.lang.management.ManagementFactory; |
| 43 | import java.lang.management.RuntimeMXBean; | 48 | import java.lang.management.RuntimeMXBean; |
| 44 | import java.net.InetSocketAddress; | 49 | import java.net.InetSocketAddress; |
| 50 | +import java.security.KeyStore; | ||
| 45 | import java.util.Dictionary; | 51 | import java.util.Dictionary; |
| 46 | import java.util.HashMap; | 52 | import java.util.HashMap; |
| 47 | import java.util.List; | 53 | import java.util.List; |
| ... | @@ -66,6 +72,8 @@ public class Controller { | ... | @@ -66,6 +72,8 @@ public class Controller { |
| 66 | 72 | ||
| 67 | protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13); | 73 | protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13); |
| 68 | protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10); | 74 | protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10); |
| 75 | + private static final boolean TLS_DISABLED = false; | ||
| 76 | + private static final short MIN_KS_LENGTH = 6; | ||
| 69 | 77 | ||
| 70 | protected HashMap<String, String> controllerNodeIPsCache; | 78 | protected HashMap<String, String> controllerNodeIPsCache; |
| 71 | 79 | ||
| ... | @@ -82,9 +90,16 @@ public class Controller { | ... | @@ -82,9 +90,16 @@ public class Controller { |
| 82 | 90 | ||
| 83 | private NioServerSocketChannelFactory execFactory; | 91 | private NioServerSocketChannelFactory execFactory; |
| 84 | 92 | ||
| 93 | + protected String ksLocation; | ||
| 94 | + protected String tsLocation; | ||
| 95 | + protected char[] ksPwd; | ||
| 96 | + protected char[] tsPwd; | ||
| 97 | + private SSLEngine serverSSLEngine; | ||
| 98 | + | ||
| 85 | // Perf. related configuration | 99 | // Perf. related configuration |
| 86 | protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024; | 100 | protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024; |
| 87 | private DriverService driverService; | 101 | private DriverService driverService; |
| 102 | + private boolean enableOFTLS = TLS_DISABLED; | ||
| 88 | 103 | ||
| 89 | // *************** | 104 | // *************** |
| 90 | // Getters/Setters | 105 | // Getters/Setters |
| ... | @@ -134,7 +149,7 @@ public class Controller { | ... | @@ -134,7 +149,7 @@ public class Controller { |
| 134 | bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); | 149 | bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE); |
| 135 | 150 | ||
| 136 | ChannelPipelineFactory pfact = | 151 | ChannelPipelineFactory pfact = |
| 137 | - new OpenflowPipelineFactory(this, null); | 152 | + new OpenflowPipelineFactory(this, null, serverSSLEngine); |
| 138 | bootstrap.setPipelineFactory(pfact); | 153 | bootstrap.setPipelineFactory(pfact); |
| 139 | cg = new DefaultChannelGroup(); | 154 | cg = new DefaultChannelGroup(); |
| 140 | openFlowPorts.forEach(port -> { | 155 | openFlowPorts.forEach(port -> { |
| ... | @@ -189,6 +204,68 @@ public class Controller { | ... | @@ -189,6 +204,68 @@ public class Controller { |
| 189 | this.controllerNodeIPsCache = new HashMap<>(); | 204 | this.controllerNodeIPsCache = new HashMap<>(); |
| 190 | 205 | ||
| 191 | this.systemStartTime = System.currentTimeMillis(); | 206 | this.systemStartTime = System.currentTimeMillis(); |
| 207 | + | ||
| 208 | + try { | ||
| 209 | + getTLSParameters(); | ||
| 210 | + if (enableOFTLS) { | ||
| 211 | + initSSL(); | ||
| 212 | + } | ||
| 213 | + } catch (Exception ex) { | ||
| 214 | + log.error("SSL init failed: {}", ex.getMessage()); | ||
| 215 | + } | ||
| 216 | + | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + private void getTLSParameters() { | ||
| 220 | + String tempString = System.getProperty("enableOFTLS"); | ||
| 221 | + enableOFTLS = Strings.isNullOrEmpty(tempString) ? TLS_DISABLED : Boolean.parseBoolean(tempString); | ||
| 222 | + log.info("OpenFlow Security is {}", enableOFTLS ? "enabled" : "disabled"); | ||
| 223 | + if (enableOFTLS) { | ||
| 224 | + ksLocation = System.getProperty("javax.net.ssl.keyStore"); | ||
| 225 | + if (Strings.isNullOrEmpty(ksLocation)) { | ||
| 226 | + enableOFTLS = TLS_DISABLED; | ||
| 227 | + return; | ||
| 228 | + } | ||
| 229 | + tsLocation = System.getProperty("javax.net.ssl.trustStore"); | ||
| 230 | + if (Strings.isNullOrEmpty(tsLocation)) { | ||
| 231 | + enableOFTLS = TLS_DISABLED; | ||
| 232 | + return; | ||
| 233 | + } | ||
| 234 | + ksPwd = System.getProperty("javax.net.ssl.keyStorePassword").toCharArray(); | ||
| 235 | + if (MIN_KS_LENGTH > ksPwd.length) { | ||
| 236 | + enableOFTLS = TLS_DISABLED; | ||
| 237 | + return; | ||
| 238 | + } | ||
| 239 | + tsPwd = System.getProperty("javax.net.ssl.trustStorePassword").toCharArray(); | ||
| 240 | + if (MIN_KS_LENGTH > tsPwd.length) { | ||
| 241 | + enableOFTLS = TLS_DISABLED; | ||
| 242 | + return; | ||
| 243 | + } | ||
| 244 | + } | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + private void initSSL() throws Exception { | ||
| 248 | + | ||
| 249 | + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); | ||
| 250 | + KeyStore ts = KeyStore.getInstance("JKS"); | ||
| 251 | + ts.load(new FileInputStream(tsLocation), tsPwd); | ||
| 252 | + tmFactory.init(ts); | ||
| 253 | + | ||
| 254 | + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); | ||
| 255 | + KeyStore ks = KeyStore.getInstance("JKS"); | ||
| 256 | + ks.load(new FileInputStream(ksLocation), ksPwd); | ||
| 257 | + kmf.init(ks, ksPwd); | ||
| 258 | + | ||
| 259 | + SSLContext serverContext = SSLContext.getInstance("TLS"); | ||
| 260 | + serverContext.init(kmf.getKeyManagers(), tmFactory.getTrustManagers(), null); | ||
| 261 | + | ||
| 262 | + serverSSLEngine = serverContext.createSSLEngine(); | ||
| 263 | + | ||
| 264 | + serverSSLEngine.setNeedClientAuth(true); | ||
| 265 | + serverSSLEngine.setUseClientMode(false); | ||
| 266 | + serverSSLEngine.setEnabledProtocols(serverSSLEngine.getSupportedProtocols()); | ||
| 267 | + serverSSLEngine.setEnabledCipherSuites(serverSSLEngine.getSupportedCipherSuites()); | ||
| 268 | + serverSSLEngine.setEnableSessionCreation(true); | ||
| 192 | } | 269 | } |
| 193 | 270 | ||
| 194 | // ************** | 271 | // ************** | ... | ... |
| ... | @@ -27,6 +27,10 @@ import org.jboss.netty.handler.timeout.ReadTimeoutHandler; | ... | @@ -27,6 +27,10 @@ import org.jboss.netty.handler.timeout.ReadTimeoutHandler; |
| 27 | import org.jboss.netty.util.ExternalResourceReleasable; | 27 | import org.jboss.netty.util.ExternalResourceReleasable; |
| 28 | import org.jboss.netty.util.HashedWheelTimer; | 28 | import org.jboss.netty.util.HashedWheelTimer; |
| 29 | import org.jboss.netty.util.Timer; | 29 | import org.jboss.netty.util.Timer; |
| 30 | +import org.slf4j.Logger; | ||
| 31 | +import org.slf4j.LoggerFactory; | ||
| 32 | + | ||
| 33 | +import javax.net.ssl.SSLEngine; | ||
| 30 | 34 | ||
| 31 | /** | 35 | /** |
| 32 | * Creates a ChannelPipeline for a server-side openflow channel. | 36 | * Creates a ChannelPipeline for a server-side openflow channel. |
| ... | @@ -34,6 +38,9 @@ import org.jboss.netty.util.Timer; | ... | @@ -34,6 +38,9 @@ import org.jboss.netty.util.Timer; |
| 34 | public class OpenflowPipelineFactory | 38 | public class OpenflowPipelineFactory |
| 35 | implements ChannelPipelineFactory, ExternalResourceReleasable { | 39 | implements ChannelPipelineFactory, ExternalResourceReleasable { |
| 36 | 40 | ||
| 41 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
| 42 | + | ||
| 43 | + private final SSLEngine sslEngine; | ||
| 37 | protected Controller controller; | 44 | protected Controller controller; |
| 38 | protected ThreadPoolExecutor pipelineExecutor; | 45 | protected ThreadPoolExecutor pipelineExecutor; |
| 39 | protected Timer timer; | 46 | protected Timer timer; |
| ... | @@ -41,13 +48,15 @@ public class OpenflowPipelineFactory | ... | @@ -41,13 +48,15 @@ public class OpenflowPipelineFactory |
| 41 | protected ReadTimeoutHandler readTimeoutHandler; | 48 | protected ReadTimeoutHandler readTimeoutHandler; |
| 42 | 49 | ||
| 43 | public OpenflowPipelineFactory(Controller controller, | 50 | public OpenflowPipelineFactory(Controller controller, |
| 44 | - ThreadPoolExecutor pipelineExecutor) { | 51 | + ThreadPoolExecutor pipelineExecutor, |
| 52 | + SSLEngine sslEngine) { | ||
| 45 | super(); | 53 | super(); |
| 46 | this.controller = controller; | 54 | this.controller = controller; |
| 47 | this.pipelineExecutor = pipelineExecutor; | 55 | this.pipelineExecutor = pipelineExecutor; |
| 48 | this.timer = new HashedWheelTimer(); | 56 | this.timer = new HashedWheelTimer(); |
| 49 | this.idleHandler = new IdleStateHandler(timer, 20, 25, 0); | 57 | this.idleHandler = new IdleStateHandler(timer, 20, 25, 0); |
| 50 | this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30); | 58 | this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30); |
| 59 | + this.sslEngine = sslEngine; | ||
| 51 | } | 60 | } |
| 52 | 61 | ||
| 53 | @Override | 62 | @Override |
| ... | @@ -55,6 +64,13 @@ public class OpenflowPipelineFactory | ... | @@ -55,6 +64,13 @@ public class OpenflowPipelineFactory |
| 55 | OFChannelHandler handler = new OFChannelHandler(controller); | 64 | OFChannelHandler handler = new OFChannelHandler(controller); |
| 56 | 65 | ||
| 57 | ChannelPipeline pipeline = Channels.pipeline(); | 66 | ChannelPipeline pipeline = Channels.pipeline(); |
| 67 | + if (sslEngine != null) { | ||
| 68 | + log.info("OpenFlow SSL enabled."); | ||
| 69 | + pipeline.addLast("ssl", | ||
| 70 | + new org.jboss.netty.handler.ssl.SslHandler(sslEngine)); | ||
| 71 | + } else { | ||
| 72 | + log.info("OpenFlow SSL disabled"); | ||
| 73 | + } | ||
| 58 | pipeline.addLast("ofmessagedecoder", new OFMessageDecoder()); | 74 | pipeline.addLast("ofmessagedecoder", new OFMessageDecoder()); |
| 59 | pipeline.addLast("ofmessageencoder", new OFMessageEncoder()); | 75 | pipeline.addLast("ofmessageencoder", new OFMessageEncoder()); |
| 60 | pipeline.addLast("idle", idleHandler); | 76 | pipeline.addLast("idle", idleHandler); | ... | ... |
-
Please register or login to post a comment