1*8542734aSAndroid Build Coastguard Worker /*
2*8542734aSAndroid Build Coastguard Worker * Copyright (C) 2012 The Android Open Source Project
3*8542734aSAndroid Build Coastguard Worker *
4*8542734aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8542734aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8542734aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8542734aSAndroid Build Coastguard Worker *
8*8542734aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8542734aSAndroid Build Coastguard Worker *
10*8542734aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8542734aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8542734aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8542734aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8542734aSAndroid Build Coastguard Worker * limitations under the License.
15*8542734aSAndroid Build Coastguard Worker */
16*8542734aSAndroid Build Coastguard Worker
17*8542734aSAndroid Build Coastguard Worker #include <set>
18*8542734aSAndroid Build Coastguard Worker
19*8542734aSAndroid Build Coastguard Worker #include <errno.h>
20*8542734aSAndroid Build Coastguard Worker #include <limits.h>
21*8542734aSAndroid Build Coastguard Worker #include <stdio.h>
22*8542734aSAndroid Build Coastguard Worker #include <stdlib.h>
23*8542734aSAndroid Build Coastguard Worker #include <string.h>
24*8542734aSAndroid Build Coastguard Worker #include <cstdint>
25*8542734aSAndroid Build Coastguard Worker
26*8542734aSAndroid Build Coastguard Worker #define LOG_TAG "FirewallController"
27*8542734aSAndroid Build Coastguard Worker #define LOG_NDEBUG 0
28*8542734aSAndroid Build Coastguard Worker
29*8542734aSAndroid Build Coastguard Worker #include <android-base/file.h>
30*8542734aSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
31*8542734aSAndroid Build Coastguard Worker #include <android-base/strings.h>
32*8542734aSAndroid Build Coastguard Worker #include <log/log.h>
33*8542734aSAndroid Build Coastguard Worker
34*8542734aSAndroid Build Coastguard Worker #include "Controllers.h"
35*8542734aSAndroid Build Coastguard Worker #include "FirewallController.h"
36*8542734aSAndroid Build Coastguard Worker #include "NetdConstants.h"
37*8542734aSAndroid Build Coastguard Worker
38*8542734aSAndroid Build Coastguard Worker using android::base::Join;
39*8542734aSAndroid Build Coastguard Worker using android::base::StringAppendF;
40*8542734aSAndroid Build Coastguard Worker using android::base::StringPrintf;
41*8542734aSAndroid Build Coastguard Worker
42*8542734aSAndroid Build Coastguard Worker namespace android {
43*8542734aSAndroid Build Coastguard Worker namespace net {
44*8542734aSAndroid Build Coastguard Worker
45*8542734aSAndroid Build Coastguard Worker auto FirewallController::execIptablesRestore = ::execIptablesRestore;
46*8542734aSAndroid Build Coastguard Worker
47*8542734aSAndroid Build Coastguard Worker const char* FirewallController::TABLE = "filter";
48*8542734aSAndroid Build Coastguard Worker
49*8542734aSAndroid Build Coastguard Worker const char* FirewallController::LOCAL_INPUT = "fw_INPUT";
50*8542734aSAndroid Build Coastguard Worker const char* FirewallController::LOCAL_OUTPUT = "fw_OUTPUT";
51*8542734aSAndroid Build Coastguard Worker const char* FirewallController::LOCAL_FORWARD = "fw_FORWARD";
52*8542734aSAndroid Build Coastguard Worker
53*8542734aSAndroid Build Coastguard Worker // ICMPv6 types that are required for any form of IPv6 connectivity to work. Note that because the
54*8542734aSAndroid Build Coastguard Worker // fw_dozable chain is called from both INPUT and OUTPUT, this includes both packets that we need
55*8542734aSAndroid Build Coastguard Worker // to be able to send (e.g., RS, NS), and packets that we need to receive (e.g., RA, NA).
56*8542734aSAndroid Build Coastguard Worker const char* FirewallController::ICMPV6_TYPES[] = {
57*8542734aSAndroid Build Coastguard Worker "packet-too-big",
58*8542734aSAndroid Build Coastguard Worker "router-solicitation",
59*8542734aSAndroid Build Coastguard Worker "router-advertisement",
60*8542734aSAndroid Build Coastguard Worker "neighbour-solicitation",
61*8542734aSAndroid Build Coastguard Worker "neighbour-advertisement",
62*8542734aSAndroid Build Coastguard Worker "redirect",
63*8542734aSAndroid Build Coastguard Worker };
64*8542734aSAndroid Build Coastguard Worker
FirewallController(void)65*8542734aSAndroid Build Coastguard Worker FirewallController::FirewallController(void) {
66*8542734aSAndroid Build Coastguard Worker // If no rules are set, it's in DENYLIST mode
67*8542734aSAndroid Build Coastguard Worker mFirewallType = DENYLIST;
68*8542734aSAndroid Build Coastguard Worker mIfaceRules = {};
69*8542734aSAndroid Build Coastguard Worker }
70*8542734aSAndroid Build Coastguard Worker
setupIptablesHooks(void)71*8542734aSAndroid Build Coastguard Worker int FirewallController::setupIptablesHooks(void) {
72*8542734aSAndroid Build Coastguard Worker return flushRules();
73*8542734aSAndroid Build Coastguard Worker }
74*8542734aSAndroid Build Coastguard Worker
setFirewallType(FirewallType ftype)75*8542734aSAndroid Build Coastguard Worker int FirewallController::setFirewallType(FirewallType ftype) {
76*8542734aSAndroid Build Coastguard Worker int res = 0;
77*8542734aSAndroid Build Coastguard Worker if (mFirewallType != ftype) {
78*8542734aSAndroid Build Coastguard Worker // flush any existing rules
79*8542734aSAndroid Build Coastguard Worker resetFirewall();
80*8542734aSAndroid Build Coastguard Worker
81*8542734aSAndroid Build Coastguard Worker if (ftype == ALLOWLIST) {
82*8542734aSAndroid Build Coastguard Worker // create default rule to drop all traffic
83*8542734aSAndroid Build Coastguard Worker std::string command =
84*8542734aSAndroid Build Coastguard Worker "*filter\n"
85*8542734aSAndroid Build Coastguard Worker "-A fw_INPUT -j DROP\n"
86*8542734aSAndroid Build Coastguard Worker "-A fw_OUTPUT -j REJECT\n"
87*8542734aSAndroid Build Coastguard Worker "-A fw_FORWARD -j REJECT\n"
88*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
89*8542734aSAndroid Build Coastguard Worker res = execIptablesRestore(V4V6, command.c_str());
90*8542734aSAndroid Build Coastguard Worker }
91*8542734aSAndroid Build Coastguard Worker
92*8542734aSAndroid Build Coastguard Worker // Set this after calling disableFirewall(), since it defaults to ALLOWLIST there
93*8542734aSAndroid Build Coastguard Worker mFirewallType = ftype;
94*8542734aSAndroid Build Coastguard Worker }
95*8542734aSAndroid Build Coastguard Worker return res ? -EREMOTEIO : 0;
96*8542734aSAndroid Build Coastguard Worker }
97*8542734aSAndroid Build Coastguard Worker
flushRules()98*8542734aSAndroid Build Coastguard Worker int FirewallController::flushRules() {
99*8542734aSAndroid Build Coastguard Worker std::string command =
100*8542734aSAndroid Build Coastguard Worker "*filter\n"
101*8542734aSAndroid Build Coastguard Worker ":fw_INPUT -\n"
102*8542734aSAndroid Build Coastguard Worker ":fw_OUTPUT -\n"
103*8542734aSAndroid Build Coastguard Worker ":fw_FORWARD -\n"
104*8542734aSAndroid Build Coastguard Worker "-6 -A fw_OUTPUT ! -o lo -s ::1 -j DROP\n"
105*8542734aSAndroid Build Coastguard Worker "COMMIT\n";
106*8542734aSAndroid Build Coastguard Worker
107*8542734aSAndroid Build Coastguard Worker return (execIptablesRestore(V4V6, command.c_str()) == 0) ? 0 : -EREMOTEIO;
108*8542734aSAndroid Build Coastguard Worker }
109*8542734aSAndroid Build Coastguard Worker
resetFirewall(void)110*8542734aSAndroid Build Coastguard Worker int FirewallController::resetFirewall(void) {
111*8542734aSAndroid Build Coastguard Worker mFirewallType = ALLOWLIST;
112*8542734aSAndroid Build Coastguard Worker mIfaceRules.clear();
113*8542734aSAndroid Build Coastguard Worker return flushRules();
114*8542734aSAndroid Build Coastguard Worker }
115*8542734aSAndroid Build Coastguard Worker
setInterfaceRule(const char * iface,FirewallRule rule)116*8542734aSAndroid Build Coastguard Worker int FirewallController::setInterfaceRule(const char* iface, FirewallRule rule) {
117*8542734aSAndroid Build Coastguard Worker if (mFirewallType == DENYLIST) {
118*8542734aSAndroid Build Coastguard Worker // Unsupported in DENYLIST mode
119*8542734aSAndroid Build Coastguard Worker return -EINVAL;
120*8542734aSAndroid Build Coastguard Worker }
121*8542734aSAndroid Build Coastguard Worker
122*8542734aSAndroid Build Coastguard Worker if (!isIfaceName(iface)) {
123*8542734aSAndroid Build Coastguard Worker errno = ENOENT;
124*8542734aSAndroid Build Coastguard Worker return -ENOENT;
125*8542734aSAndroid Build Coastguard Worker }
126*8542734aSAndroid Build Coastguard Worker
127*8542734aSAndroid Build Coastguard Worker // Only delete rules if we actually added them, because otherwise our iptables-restore
128*8542734aSAndroid Build Coastguard Worker // processes will terminate with "no such rule" errors and cause latency penalties while we
129*8542734aSAndroid Build Coastguard Worker // spin up new ones.
130*8542734aSAndroid Build Coastguard Worker const char* op;
131*8542734aSAndroid Build Coastguard Worker if (rule == ALLOW && mIfaceRules.find(iface) == mIfaceRules.end()) {
132*8542734aSAndroid Build Coastguard Worker op = "-I";
133*8542734aSAndroid Build Coastguard Worker mIfaceRules.insert(iface);
134*8542734aSAndroid Build Coastguard Worker } else if (rule == DENY && mIfaceRules.find(iface) != mIfaceRules.end()) {
135*8542734aSAndroid Build Coastguard Worker op = "-D";
136*8542734aSAndroid Build Coastguard Worker mIfaceRules.erase(iface);
137*8542734aSAndroid Build Coastguard Worker } else {
138*8542734aSAndroid Build Coastguard Worker return 0;
139*8542734aSAndroid Build Coastguard Worker }
140*8542734aSAndroid Build Coastguard Worker
141*8542734aSAndroid Build Coastguard Worker std::string command = Join(std::vector<std::string> {
142*8542734aSAndroid Build Coastguard Worker "*filter",
143*8542734aSAndroid Build Coastguard Worker StringPrintf("%s fw_INPUT -i %s -j RETURN", op, iface),
144*8542734aSAndroid Build Coastguard Worker StringPrintf("%s fw_OUTPUT -o %s -j RETURN", op, iface),
145*8542734aSAndroid Build Coastguard Worker "COMMIT\n"
146*8542734aSAndroid Build Coastguard Worker }, "\n");
147*8542734aSAndroid Build Coastguard Worker return (execIptablesRestore(V4V6, command) == 0) ? 0 : -EREMOTEIO;
148*8542734aSAndroid Build Coastguard Worker }
149*8542734aSAndroid Build Coastguard Worker
150*8542734aSAndroid Build Coastguard Worker /* static */
makeCriticalCommands(IptablesTarget target,const char * chainName)151*8542734aSAndroid Build Coastguard Worker std::string FirewallController::makeCriticalCommands(IptablesTarget target, const char* chainName) {
152*8542734aSAndroid Build Coastguard Worker // Allow ICMPv6 packets necessary to make IPv6 connectivity work. http://b/23158230 .
153*8542734aSAndroid Build Coastguard Worker std::string commands;
154*8542734aSAndroid Build Coastguard Worker if (target == V6) {
155*8542734aSAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(ICMPV6_TYPES); i++) {
156*8542734aSAndroid Build Coastguard Worker StringAppendF(&commands, "-A %s -p icmpv6 --icmpv6-type %s -j RETURN\n",
157*8542734aSAndroid Build Coastguard Worker chainName, ICMPV6_TYPES[i]);
158*8542734aSAndroid Build Coastguard Worker }
159*8542734aSAndroid Build Coastguard Worker }
160*8542734aSAndroid Build Coastguard Worker return commands;
161*8542734aSAndroid Build Coastguard Worker }
162*8542734aSAndroid Build Coastguard Worker
163*8542734aSAndroid Build Coastguard Worker } // namespace net
164*8542734aSAndroid Build Coastguard Worker } // namespace android
165