diff --git a/src/main/java/net/floodlightcontroller/firewall/Firewall.java b/src/main/java/net/floodlightcontroller/firewall/Firewall.java index 0b2a849b2d4f936d9d3a49bf6f3e8cbdcb6265e2..3a78c9d1eb6f5089b41831e621538eb808b3e80a 100644 --- a/src/main/java/net/floodlightcontroller/firewall/Firewall.java +++ b/src/main/java/net/floodlightcontroller/firewall/Firewall.java @@ -28,6 +28,7 @@ import org.projectfloodlight.openflow.protocol.OFMessage; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFType; import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.protocol.match.Match; import org.projectfloodlight.openflow.protocol.match.MatchField; import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.EthType; @@ -52,12 +53,15 @@ import java.util.ArrayList; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; +import net.floodlightcontroller.packet.TCP; +import net.floodlightcontroller.packet.UDP; import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.routing.IRoutingDecision; import net.floodlightcontroller.routing.RoutingDecision; import net.floodlightcontroller.storage.IResultSet; import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.StorageException; +import net.floodlightcontroller.util.MatchUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -481,7 +485,38 @@ public class Firewall implements IFirewallService, IOFMessageListener, // make a pair of rule and wildcards, then return it RuleMatchPair rmp = new RuleMatchPair(); rmp.rule = matched_rule; - if (matched_rule == null || matched_rule.action == FirewallRule.FirewallAction.DROP) { + if (matched_rule == null) { + /* + * No rule was found, so drop the packet with as specific + * of a drop rule as possible as not to interfere with other + * firewall rules. + */ + Match.Builder mb = MatchUtils.createRetentiveBuilder(pi.getMatch()); // capture the ingress port + mb.setExact(MatchField.ETH_SRC, eth.getSourceMACAddress()) + .setExact(MatchField.ETH_DST, eth.getDestinationMACAddress()) + .setExact(MatchField.ETH_TYPE, EthType.of(eth.getEtherType())); + + if (mb.get(MatchField.ETH_TYPE).equals(EthType.IPv4)) { + IPv4 ipv4 = (IPv4) eth.getPayload(); + mb.setExact(MatchField.IPV4_SRC, ipv4.getSourceAddress()) + .setExact(MatchField.IPV4_DST, ipv4.getDestinationAddress()) + .setExact(MatchField.IP_PROTO, ipv4.getProtocol()); + + if (mb.get(MatchField.IP_PROTO).equals(IpProtocol.TCP)) { + TCP tcp = (TCP) ipv4.getPayload(); + mb.setExact(MatchField.TCP_SRC, tcp.getSourcePort()) + .setExact(MatchField.TCP_DST, tcp.getDestinationPort()); + } else if (mb.get(MatchField.IP_PROTO).equals(IpProtocol.UDP)) { + UDP udp = (UDP) ipv4.getPayload(); + mb.setExact(MatchField.UDP_SRC, udp.getSourcePort()) + .setExact(MatchField.UDP_DST, udp.getDestinationPort()); + } else { + // could be ICMP, which will be taken care of via IPv4 src/dst + ip proto + } + } + rmp.match = mb.build(); + //rmp.match = adp.drop.build(); This inserted a "drop all" rule if no match was found (not what we want to do...) + } else if (matched_rule.action == FirewallRule.FirewallAction.DROP) { rmp.match = adp.drop.build(); } else { rmp.match = adp.allow.build(); diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java index 03f9baef2c2e07c9876f2aebaa6abaf758aa1539..773a450e12480cbe2f845b13dee89d98b1d1fc53 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java @@ -69,7 +69,7 @@ public class FirewallResource extends ServerResource { // REST API set local subnet mask -- this only makes sense for one subnet // will remove later if (op.equalsIgnoreCase("subnet-mask")) { - return firewall.getSubnetMask(); + return "{\"subnet-mask\":\"" + firewall.getSubnetMask() + "\"}"; } // no known options found diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java index 9f6fc1e217392610017ee4edb00e1a657ab7c9df..441c4305c3ce2f5e18b4f2a12f10a2981e3ecb65 100644 --- a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java +++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java @@ -293,10 +293,14 @@ public class FirewallRule implements Comparable<FirewallRule> { return false; if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_IN_PORT; - adp.drop.setExact(MatchField.IN_PORT, this.in_port); + if (!OFPort.ANY.equals(this.in_port)) { + adp.drop.setExact(MatchField.IN_PORT, this.in_port); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_IN_PORT; - adp.allow.setExact(MatchField.IN_PORT, this.in_port); + if (!OFPort.ANY.equals(this.in_port)) { + adp.allow.setExact(MatchField.IN_PORT, this.in_port); + } } // mac address (src and dst) match? @@ -304,20 +308,28 @@ public class FirewallRule implements Comparable<FirewallRule> { return false; if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_SRC; - adp.drop.setExact(MatchField.ETH_SRC, this.dl_src); + if (!MacAddress.NONE.equals(this.dl_src)) { + adp.drop.setExact(MatchField.ETH_SRC, this.dl_src); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_DL_SRC; - adp.allow.setExact(MatchField.ETH_SRC, this.dl_src); + if (!MacAddress.NONE.equals(this.dl_src)) { + adp.allow.setExact(MatchField.ETH_SRC, this.dl_src); + } } if (any_dl_dst == false && !dl_dst.equals(packet.getDestinationMACAddress())) return false; if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_DST; - adp.drop.setExact(MatchField.ETH_DST, this.dl_dst); + if (!MacAddress.NONE.equals(this.dl_dst)) { + adp.drop.setExact(MatchField.ETH_DST, this.dl_dst); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_DL_DST; - adp.allow.setExact(MatchField.ETH_DST, this.dl_dst); + if (!MacAddress.NONE.equals(this.dl_dst)) { + adp.allow.setExact(MatchField.ETH_DST, this.dl_dst); + } } // dl_type check: ARP, IP @@ -331,10 +343,14 @@ public class FirewallRule implements Comparable<FirewallRule> { else { if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; - adp.drop.setExact(MatchField.ETH_TYPE, this.dl_type); + if (!EthType.NONE.equals(this.dl_type)) { + adp.drop.setExact(MatchField.ETH_TYPE, this.dl_type); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE; - adp.allow.setExact(MatchField.ETH_TYPE, this.dl_type); + if (!EthType.NONE.equals(this.dl_type)) { + adp.allow.setExact(MatchField.ETH_TYPE, this.dl_type); + } } } } else if (dl_type.equals(EthType.IPv4)) { @@ -343,10 +359,14 @@ public class FirewallRule implements Comparable<FirewallRule> { else { if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; - adp.drop.setExact(MatchField.IP_PROTO, this.nw_proto); + if (!IpProtocol.NONE.equals(this.nw_proto)) { + adp.drop.setExact(MatchField.IP_PROTO, this.nw_proto); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO; - adp.allow.setExact(MatchField.IP_PROTO, this.nw_proto); + if (!IpProtocol.NONE.equals(this.nw_proto)) { + adp.allow.setExact(MatchField.IP_PROTO, this.nw_proto); + } } // IP packets, proceed with ip address check pkt_ip = (IPv4) pkt; @@ -357,11 +377,15 @@ public class FirewallRule implements Comparable<FirewallRule> { if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL; //wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT); - adp.drop.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask); + if (!IPv4AddressWithMask.NONE.equals(this.nw_src_prefix_and_mask)) { + adp.drop.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_NW_SRC_ALL; //wildcards.allow |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT); - adp.allow.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask); + if (!IPv4AddressWithMask.NONE.equals(this.nw_src_prefix_and_mask)) { + adp.allow.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask); + } } if (any_nw_dst == false && !nw_dst_prefix_and_mask.matches(pkt_ip.getDestinationAddress())) @@ -369,11 +393,15 @@ public class FirewallRule implements Comparable<FirewallRule> { if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL; //wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT); - adp.drop.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask); + if (!IPv4AddressWithMask.NONE.equals(this.nw_dst_prefix_and_mask)) { + adp.drop.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_NW_DST_ALL; //wildcards.allow |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT); - adp.allow.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask); + if (!IPv4AddressWithMask.NONE.equals(this.nw_dst_prefix_and_mask)) { + adp.allow.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask); + } } // nw_proto check @@ -403,10 +431,14 @@ public class FirewallRule implements Comparable<FirewallRule> { } if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO; - adp.drop.setExact(MatchField.IP_PROTO, this.nw_proto); + if (!IpProtocol.NONE.equals(this.nw_proto)) { + adp.drop.setExact(MatchField.IP_PROTO, this.nw_proto); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO; - adp.allow.setExact(MatchField.IP_PROTO, this.nw_proto); + if (!IpProtocol.NONE.equals(this.nw_proto)) { + adp.allow.setExact(MatchField.IP_PROTO, this.nw_proto); + } } // TCP/UDP source and destination ports match? @@ -418,16 +450,24 @@ public class FirewallRule implements Comparable<FirewallRule> { if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_TP_SRC; if (pkt_tcp != null) { - adp.drop.setExact(MatchField.TCP_SRC, this.tp_src); + if (!TransportPort.NONE.equals(this.tp_src)) { + adp.drop.setExact(MatchField.TCP_SRC, this.tp_src); + } } else { - adp.drop.setExact(MatchField.UDP_SRC, this.tp_src); + if (!TransportPort.NONE.equals(this.tp_src)) { + adp.drop.setExact(MatchField.UDP_SRC, this.tp_src); + } } } else { //wildcards.allow &= ~OFMatch.OFPFW_TP_SRC; if (pkt_tcp != null) { - adp.allow.setExact(MatchField.TCP_SRC, this.tp_src); + if (!TransportPort.NONE.equals(this.tp_src)) { + adp.allow.setExact(MatchField.TCP_SRC, this.tp_src); + } } else { - adp.allow.setExact(MatchField.UDP_SRC, this.tp_src); + if (!TransportPort.NONE.equals(this.tp_src)) { + adp.allow.setExact(MatchField.UDP_SRC, this.tp_src); + } } } @@ -438,16 +478,24 @@ public class FirewallRule implements Comparable<FirewallRule> { if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_TP_DST; if (pkt_tcp != null) { - adp.drop.setExact(MatchField.TCP_DST, this.tp_dst); + if (!TransportPort.NONE.equals(this.tp_dst)) { + adp.drop.setExact(MatchField.TCP_DST, this.tp_dst); + } } else { - adp.drop.setExact(MatchField.UDP_DST, this.tp_dst); + if (!TransportPort.NONE.equals(this.tp_dst)) { + adp.drop.setExact(MatchField.UDP_DST, this.tp_dst); + } } } else { //wildcards.allow &= ~OFMatch.OFPFW_TP_DST; if (pkt_tcp != null) { - adp.allow.setExact(MatchField.TCP_DST, this.tp_dst); + if (!TransportPort.NONE.equals(this.tp_dst)) { + adp.allow.setExact(MatchField.TCP_DST, this.tp_dst); + } } else { - adp.allow.setExact(MatchField.UDP_DST, this.tp_dst); + if (!TransportPort.NONE.equals(this.tp_dst)) { + adp.allow.setExact(MatchField.UDP_DST, this.tp_dst); + } } } } @@ -461,10 +509,14 @@ public class FirewallRule implements Comparable<FirewallRule> { } if (action == FirewallRule.FirewallAction.DROP) { //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE; - adp.drop.setExact(MatchField.ETH_TYPE, this.dl_type); + if (!EthType.NONE.equals(this.dl_type)) { + adp.drop.setExact(MatchField.ETH_TYPE, this.dl_type); + } } else { //wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE; - adp.allow.setExact(MatchField.ETH_TYPE, this.dl_type); + if (!EthType.NONE.equals(this.dl_type)) { + adp.allow.setExact(MatchField.ETH_TYPE, this.dl_type); + } } // all applicable checks passed diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule index b78286cb5786bdfe789940612061b096e130127b..35e68d9da1a7cea34969cfbf1e47a01cdf015a50 100644 --- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule +++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule @@ -22,4 +22,5 @@ net.floodlightcontroller.topology.TopologyManager net.floodlightcontroller.forwarding.Forwarding net.floodlightcontroller.loadbalancer.LoadBalancer net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager -net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl \ No newline at end of file +net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl +net.floodlightcontroller.firewall.Firewall \ No newline at end of file diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties index 108f661d8f847afa785584b1e30ec821df7d5351..9dc689f7c13e5747767911972295aa0c94604088 100644 --- a/src/main/resources/floodlightdefault.properties +++ b/src/main/resources/floodlightdefault.properties @@ -13,6 +13,7 @@ net.floodlightcontroller.forwarding.Forwarding,\ net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager,\ net.floodlightcontroller.ui.web.StaticWebRoutable,\ net.floodlightcontroller.loadbalancer.LoadBalancer,\ +net.floodlightcontroller.firewall.Firewall,\ net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl org.sdnplatform.sync.internal.SyncManager.authScheme=CHALLENGE_RESPONSE org.sdnplatform.sync.internal.SyncManager.keyStorePath=/etc/floodlight/auth_credentials.jceks diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml index 7255c24f726da5ee346747672ce4df92648e8909..c78003320228840936488f4a459e35369629a41e 100644 --- a/src/main/resources/logback-test.xml +++ b/src/main/resources/logback-test.xml @@ -19,4 +19,5 @@ <logger name="net.floodlightcontroller.forwarding" level="INFO"></logger> <logger name="net.floodlightcontroller.routing" level="INFO"></logger> <logger name="net.floodlightcontroller.core" level="INFO"></logger> + <logger level="DEBUG" name="net.floodlightcontroller.firewall"></logger> </configuration>