mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-299: Egress firewall rules feature for guest network on VR
This commit is contained in:
parent
ae3d8aa018
commit
48fdc25daa
@ -0,0 +1,341 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.package org.apache.cloudstack.api.command.user.firewall;
|
||||
|
||||
package org.apache.cloudstack.api.command.user.firewall;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.FirewallResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkResponse;
|
||||
|
||||
import com.cloud.async.AsyncJob;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.NetworkRuleConflictException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.rules.FirewallRule;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
@APICommand(name = "createEgressFirewallRule", description = "Creates a egress firewall rule for a given network ", responseObject = FirewallResponse.class)
|
||||
public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule {
|
||||
public static final Logger s_logger = Logger.getLogger(CreateEgressFirewallRuleCmd.class.getName());
|
||||
|
||||
private static final String s_name = "createegressfirewallruleresponse";
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ////////////// API parameters /////////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
||||
@Parameter (name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "the network id of the port forwarding rule")
|
||||
private Long networkId;
|
||||
|
||||
@Parameter(name = ApiConstants.PROTOCOL, type = CommandType.STRING, required = true, description = "the protocol for the firewall rule. Valid values are TCP/UDP/ICMP.")
|
||||
private String protocol;
|
||||
|
||||
@Parameter(name = ApiConstants.START_PORT, type = CommandType.INTEGER, description = "the starting port of firewall rule")
|
||||
private Integer publicStartPort;
|
||||
|
||||
@Parameter(name = ApiConstants.END_PORT, type = CommandType.INTEGER, description = "the ending port of firewall rule")
|
||||
private Integer publicEndPort;
|
||||
|
||||
@Parameter(name = ApiConstants.CIDR_LIST, type = CommandType.LIST, collectionType = CommandType.STRING, description = "the cidr list to forward traffic from")
|
||||
private List<String> cidrlist;
|
||||
|
||||
@Parameter(name = ApiConstants.ICMP_TYPE, type = CommandType.INTEGER, description = "type of the icmp message being sent")
|
||||
private Integer icmpType;
|
||||
|
||||
@Parameter(name = ApiConstants.ICMP_CODE, type = CommandType.INTEGER, description = "error code for this icmp message")
|
||||
private Integer icmpCode;
|
||||
|
||||
@Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = "type of firewallrule: system/user")
|
||||
private String type;
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////////// Accessors ///////////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
||||
public Long getIpAddressId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
return protocol.trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSourceCidrList() {
|
||||
if (cidrlist != null) {
|
||||
return cidrlist;
|
||||
} else {
|
||||
List<String> oneCidrList = new ArrayList<String>();
|
||||
oneCidrList.add(_networkService.getNetwork(networkId).getCidr());
|
||||
return oneCidrList;
|
||||
}
|
||||
}
|
||||
|
||||
public Long getVpcId() {
|
||||
Network network = _networkService.getNetwork(getNetworkId());
|
||||
if (network == null) {
|
||||
throw new InvalidParameterValueException("Invalid networkId is given");
|
||||
}
|
||||
|
||||
Long vpcId = network.getVpcId();
|
||||
return vpcId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////// API Implementation///////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
public void setSourceCidrList(List<String> cidrs){
|
||||
cidrlist = cidrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException {
|
||||
UserContext callerContext = UserContext.current();
|
||||
boolean success = false;
|
||||
FirewallRule rule = _entityMgr.findById(FirewallRule.class, getEntityId());
|
||||
try {
|
||||
UserContext.current().setEventDetails("Rule Id: " + getEntityId());
|
||||
success = _firewallService.applyEgressFirewallRules (rule, callerContext.getCaller());
|
||||
// State is different after the rule is applied, so get new object here
|
||||
rule = _entityMgr.findById(FirewallRule.class, getEntityId());
|
||||
FirewallResponse fwResponse = new FirewallResponse();
|
||||
if (rule != null) {
|
||||
fwResponse = _responseGenerator.createFirewallResponse(rule);
|
||||
setResponseObject(fwResponse);
|
||||
}
|
||||
fwResponse.setResponseName(getCommandName());
|
||||
} finally {
|
||||
if (!success || rule == null) {
|
||||
_firewallService.revokeFirewallRule(getEntityId(), true);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create firewall rule");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
throw new UnsupportedOperationException("database id can only provided by VO objects");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getXid() {
|
||||
// FIXME: We should allow for end user to specify Xid.
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSourceIpAddressId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getSourcePortStart() {
|
||||
if (publicStartPort != null) {
|
||||
return publicStartPort.intValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getSourcePortEnd() {
|
||||
if (publicEndPort == null) {
|
||||
if (publicStartPort != null) {
|
||||
return publicStartPort.intValue();
|
||||
}
|
||||
} else {
|
||||
return publicEndPort.intValue();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Purpose getPurpose() {
|
||||
return Purpose.Firewall;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
throw new UnsupportedOperationException("Should never call me to find the state");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Account account = UserContext.current().getCaller();
|
||||
|
||||
if (account != null) {
|
||||
return account.getId();
|
||||
}
|
||||
|
||||
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDomainId() {
|
||||
Network network =_networkService.getNetwork(networkId);
|
||||
return network.getDomainId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
if (getSourceCidrList() != null) {
|
||||
String guestCidr = _networkService.getNetwork(getNetworkId()).getCidr();
|
||||
|
||||
for (String cidr: getSourceCidrList()){
|
||||
if (!NetUtils.isValidCIDR(cidr)){
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr);
|
||||
}
|
||||
if (cidr.equals(NetUtils.ALL_CIDRS)) {
|
||||
continue;
|
||||
}
|
||||
if(!NetUtils.isNetworkAWithinNetworkB(cidr, guestCidr)) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, cidr + "is not within the guest cidr " + guestCidr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (getProtocol().equalsIgnoreCase(NetUtils.ALL_PROTO)) {
|
||||
if (getSourcePortStart() != null && getSourcePortEnd() != null) {
|
||||
throw new InvalidParameterValueException("Do not pass ports to protocol ALL, porotocol ALL do not require ports. Unable to create "
|
||||
+"firewall rule for the network id=" + networkId);
|
||||
}
|
||||
}
|
||||
|
||||
if (getVpcId() != null ){
|
||||
throw new InvalidParameterValueException("Unable to create firewall rule for the network id=" + networkId +
|
||||
" as firewall egress rule can be created only for non vpc networks.");
|
||||
}
|
||||
|
||||
try {
|
||||
FirewallRule result = _firewallService.createEgressFirewallRule(this);
|
||||
setEntityId(result.getId());
|
||||
} catch (NetworkRuleConflictException ex) {
|
||||
s_logger.info("Network rule conflict: " + ex.getMessage());
|
||||
s_logger.trace("Network Rule Conflict: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.NETWORK_RULE_CONFLICT_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_FIREWALL_OPEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
Network network = _networkService.getNetwork(networkId);
|
||||
return ("Creating firewall rule for network: " + network + " for protocol:" + this.getProtocol());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getAccountId() {
|
||||
Network network = _networkService.getNetwork(networkId);
|
||||
return network.getAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSyncObjType() {
|
||||
return BaseAsyncCmd.networkSyncObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSyncObjId() {
|
||||
return getNetworkId();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Integer getIcmpCode() {
|
||||
if (icmpCode != null) {
|
||||
return icmpCode;
|
||||
} else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
|
||||
return -1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIcmpType() {
|
||||
if (icmpType != null) {
|
||||
return icmpType;
|
||||
} else if (protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO)) {
|
||||
return -1;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getRelated() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FirewallRuleType getType() {
|
||||
if (type != null && type.equalsIgnoreCase("system")) {
|
||||
return FirewallRuleType.System;
|
||||
} else {
|
||||
return FirewallRuleType.User;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncJob.Type getInstanceType() {
|
||||
return AsyncJob.Type.FirewallRule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrafficType getTrafficType() {
|
||||
return TrafficType.Egress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,120 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.package org.apache.cloudstack.api.command.user.firewall;
|
||||
|
||||
package org.apache.cloudstack.api.command.user.firewall;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.SuccessResponse;
|
||||
import com.cloud.async.AsyncJob;
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.rules.FirewallRule;
|
||||
import com.cloud.user.UserContext;
|
||||
|
||||
@APICommand(name = "deleteEgressFirewallRule", description="Deletes an ggress firewall rule", responseObject=SuccessResponse.class)
|
||||
public class DeleteEgressFirewallRuleCmd extends BaseAsyncCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(DeleteEgressFirewallRuleCmd.class.getName());
|
||||
private static final String s_name = "deleteegressfirewallruleresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="the ID of the firewall rule")
|
||||
private Long id;
|
||||
|
||||
// unexposed parameter needed for events logging
|
||||
@Parameter(name=ApiConstants.ACCOUNT_ID, type=CommandType.LONG, expose=false)
|
||||
private Long ownerId;
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_FIREWALL_CLOSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return ("Deleting egress firewall rule id=" + id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
if (ownerId == null) {
|
||||
FirewallRule rule = _entityMgr.findById(FirewallRule.class, id);
|
||||
if (rule == null) {
|
||||
throw new InvalidParameterValueException("Unable to find egress firewall rule by id");
|
||||
} else {
|
||||
ownerId = _entityMgr.findById(FirewallRule.class, id).getAccountId();
|
||||
}
|
||||
}
|
||||
return ownerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException {
|
||||
UserContext.current().setEventDetails("Rule Id: " + id);
|
||||
boolean result = _firewallService.revokeFirewallRule(id, true);
|
||||
|
||||
if (result) {
|
||||
SuccessResponse response = new SuccessResponse(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete egress firewall rule");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getSyncObjType() {
|
||||
return BaseAsyncCmd.networkSyncObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getSyncObjId() {
|
||||
return _firewallService.getFirewallRule(id).getNetworkId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncJob.Type getInstanceType() {
|
||||
return AsyncJob.Type.FirewallRule;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.package org.apache.cloudstack.api.command.user.firewall;
|
||||
|
||||
package org.apache.cloudstack.api.command.user.firewall;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseListTaggedResourcesCmd;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.FirewallResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import com.cloud.network.rules.FirewallRule;
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
@APICommand(name = "listEgressFirewallRules", description="Lists all egress firewall rules for network id.", responseObject=FirewallResponse.class)
|
||||
public class ListEgressFirewallRulesCmd extends ListFirewallRulesCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(ListEgressFirewallRulesCmd.class.getName());
|
||||
private static final String s_name = "listegressfirewallrulesresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@Parameter(name=ApiConstants.ID, type=CommandType.LONG, description="Lists rule with the specified ID.")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.LONG, description="the id network network for the egress firwall services")
|
||||
private Long networkId;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public FirewallRule.TrafficType getTrafficType () {
|
||||
return FirewallRule.TrafficType.Egress;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(){
|
||||
Pair<List<? extends FirewallRule>, Integer> result = _firewallService.listFirewallRules(this);
|
||||
ListResponse<FirewallResponse> response = new ListResponse<FirewallResponse>();
|
||||
List<FirewallResponse> fwResponses = new ArrayList<FirewallResponse>();
|
||||
|
||||
for (FirewallRule fwRule : result.first()) {
|
||||
FirewallResponse ruleData = _responseGenerator.createFirewallResponse(fwRule);
|
||||
ruleData.setObjectName("firewallrule");
|
||||
fwResponses.add(ruleData);
|
||||
}
|
||||
response.setResponses(fwResponses, result.second());
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
}
|
||||
}
|
||||
171
patches/systemvm/debian/config/root/firewallRule_egress.sh
Executable file
171
patches/systemvm/debian/config/root/firewallRule_egress.sh
Executable file
@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env bash
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# $Id: firewallRule_egress.sh 9947 2013-01-17 19:34:24Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/patches/xenserver/root/firewallRule_egress.sh $
|
||||
# firewallRule_egress.sh -- allow some ports / protocols from vm instances
|
||||
# @VERSION@
|
||||
|
||||
source /root/func.sh
|
||||
|
||||
lock="biglock"
|
||||
locked=$(getLockFile $lock)
|
||||
if [ "$locked" != "1" ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
#set -x
|
||||
usage() {
|
||||
printf "Usage: %s: -a protocol:startport:endport:sourcecidrs> \n" $(basename $0) >&2
|
||||
printf "sourcecidrs format: cidr1-cidr2-cidr3-...\n"
|
||||
}
|
||||
|
||||
fw_egress_remove_backup() {
|
||||
sudo iptables -D FW_OUTBOUND -j _FW_EGRESS_RULES
|
||||
sudo iptables -F _FW_EGRESS_RULES
|
||||
sudo iptables -X _FW_EGRESS_RULES
|
||||
}
|
||||
|
||||
fw_egress_save() {
|
||||
sudo iptables -E FW_EGRESS_RULES _FW_EGRESS_RULES
|
||||
}
|
||||
|
||||
fw_egress_chain () {
|
||||
#supress errors 2>/dev/null
|
||||
fw_egress_remove_backup
|
||||
fw_egress_save
|
||||
sudo iptables -N FW_EGRESS_RULES
|
||||
sudo iptables -A FW_OUTBOUND -j FW_EGRESS_RULES
|
||||
}
|
||||
|
||||
fw_egress_backup_restore() {
|
||||
sudo iptables -A FW_OUTBOUND -j FW_EGRESS_RULES
|
||||
sudo iptables -E _FW_EGRESS_RULES FW_EGRESS_RULES
|
||||
fw_egress_remove_backup
|
||||
}
|
||||
|
||||
|
||||
fw_entry_for_egress() {
|
||||
local rule=$1
|
||||
|
||||
local prot=$(echo $rule | cut -d: -f2)
|
||||
local sport=$(echo $rule | cut -d: -f3)
|
||||
local eport=$(echo $rule | cut -d: -f4)
|
||||
local cidrs=$(echo $rule | cut -d: -f5 | sed 's/-/ /g')
|
||||
if [ "$sport" == "0" -a "$eport" == "0" ]
|
||||
then
|
||||
DPORT=""
|
||||
else
|
||||
DPORT="--dport $sport:$eport"
|
||||
fi
|
||||
logger -t cloud "$(basename $0): enter apply fw egress rules for guest $prot:$sport:$eport:$cidrs"
|
||||
|
||||
for lcidr in $cidrs
|
||||
do
|
||||
[ "$prot" == "reverted" ] && continue;
|
||||
if [ "$prot" == "icmp" ]
|
||||
then
|
||||
typecode="$sport/$eport"
|
||||
[ "$eport" == "-1" ] && typecode="$sport"
|
||||
[ "$sport" == "-1" ] && typecode="any"
|
||||
sudo iptables -A FW_EGRESS_RULES -p $prot -s $lcidr --icmp-type $typecode \
|
||||
-j ACCEPT
|
||||
result=$?
|
||||
elif [ "$prot" == "all" ]
|
||||
then
|
||||
sudo iptables -A FW_EGRESS_RULES -p $prot -s $lcidr -j ACCEPT
|
||||
result=$?
|
||||
else
|
||||
sudo iptables -A FW_EGRESS_RULES -p $prot -s $lcidr \
|
||||
$DPORT -j ACCEPT
|
||||
result=$?
|
||||
fi
|
||||
|
||||
[ $result -gt 0 ] &&
|
||||
logger -t cloud "Error adding iptables entry for guest network $prot:$sport:$eport:$cidrs" &&
|
||||
break
|
||||
done
|
||||
|
||||
logger -t cloud "$(basename $0): exit apply egress firewall rules for guest network"
|
||||
return $result
|
||||
}
|
||||
|
||||
|
||||
aflag=0
|
||||
rules=""
|
||||
rules_list=""
|
||||
ip=""
|
||||
dev=""
|
||||
shift
|
||||
shift
|
||||
while getopts 'a:' OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
a) aflag=1
|
||||
rules="$OPTARG"
|
||||
;;
|
||||
?) usage
|
||||
unlock_exit 2 $lock $locked
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$aflag" != "1" ]
|
||||
then
|
||||
usage
|
||||
unlock_exit 2 $lock $locked
|
||||
fi
|
||||
|
||||
if [ -n "$rules" ]
|
||||
then
|
||||
rules_list=$(echo $rules | cut -d, -f1- --output-delimiter=" ")
|
||||
fi
|
||||
|
||||
# rule format
|
||||
# protocal:sport:eport:cidr
|
||||
#-a tcp:80:80:0.0.0.0/0::tcp:220:220:0.0.0.0/0:,tcp:222:222:192.168.10.0/24-75.57.23.0/22-88.100.33.1/32
|
||||
# if any entry is reverted , entry will be in the format reverted:0:0:0
|
||||
# example : tcp:80:80:0.0.0.0/0:, tcp:220:220:0.0.0.0/0:,200.1.1.2:reverted:0:0:0
|
||||
|
||||
success=0
|
||||
|
||||
fw_egress_chain
|
||||
for r in $rules_list
|
||||
do
|
||||
fw_entry_for_egress $r
|
||||
success=$?
|
||||
if [ $success -gt 0 ]
|
||||
then
|
||||
logger -t cloud "failure to apply fw egress rules "
|
||||
break
|
||||
else
|
||||
logger -t cloud "successful in applying fw egress rules"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $success -gt 0 ]
|
||||
then
|
||||
logger -t cloud "restoring from backup for guest network"
|
||||
fw_egress_backup_restore
|
||||
else
|
||||
logger -t cloud "deleting backup for guest network"
|
||||
fi
|
||||
|
||||
fw_egress_remove_backup
|
||||
|
||||
unlock_exit $success $lock $locked
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user