1 /* 2 * firewall3 - 3rd OpenWrt UCI firewall implementation 3 * 4 * Copyright (C) 2013 Jo-Philipp Wich <jo@mein.io> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "defaults.h" 20 21 22 #define C(f, tbl, def, fmt) \ 23 { FW3_FAMILY_##f, FW3_TABLE_##tbl, FW3_FLAG_##def, fmt } 24 25 static const struct fw3_chain_spec default_chains[] = { 26 C(ANY, FILTER, UNSPEC, "reject"), 27 C(ANY, FILTER, CUSTOM_CHAINS, "input_rule"), 28 C(ANY, FILTER, CUSTOM_CHAINS, "output_rule"), 29 C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_rule"), 30 C(ANY, FILTER, SYN_FLOOD, "syn_flood"), 31 32 C(V4, NAT, CUSTOM_CHAINS, "prerouting_rule"), 33 C(V4, NAT, CUSTOM_CHAINS, "postrouting_rule"), 34 35 { } 36 }; 37 38 const struct fw3_option fw3_flag_opts[] = { 39 FW3_OPT("input", target, defaults, policy_input), 40 FW3_OPT("forward", target, defaults, policy_forward), 41 FW3_OPT("output", target, defaults, policy_output), 42 43 FW3_OPT("drop_invalid", bool, defaults, drop_invalid), 44 FW3_OPT("tcp_reject_code", reject_code, defaults, tcp_reject_code), 45 FW3_OPT("any_reject_code", reject_code, defaults, any_reject_code), 46 47 FW3_OPT("syn_flood", bool, defaults, syn_flood), 48 FW3_OPT("synflood_protect", bool, defaults, syn_flood), 49 FW3_OPT("synflood_rate", limit, defaults, syn_flood_rate), 50 FW3_OPT("synflood_burst", int, defaults, syn_flood_rate.burst), 51 52 FW3_OPT("tcp_syncookies", bool, defaults, tcp_syncookies), 53 FW3_OPT("tcp_ecn", int, defaults, tcp_ecn), 54 FW3_OPT("tcp_window_scaling", bool, defaults, tcp_window_scaling), 55 56 FW3_OPT("accept_redirects", bool, defaults, accept_redirects), 57 FW3_OPT("accept_source_route", bool, defaults, accept_source_route), 58 59 FW3_OPT("auto_helper", bool, defaults, auto_helper), 60 FW3_OPT("custom_chains", bool, defaults, custom_chains), 61 FW3_OPT("disable_ipv6", bool, defaults, disable_ipv6), 62 FW3_OPT("flow_offloading", bool, defaults, flow_offloading), 63 FW3_OPT("flow_offloading_hw", bool, defaults, flow_offloading_hw), 64 65 FW3_OPT("__flags_v4", int, defaults, flags[0]), 66 FW3_OPT("__flags_v6", int, defaults, flags[1]), 67 68 { } 69 }; 70 71 72 static void 73 check_policy(struct uci_element *e, enum fw3_flag *pol, const char *name) 74 { 75 if (*pol == FW3_FLAG_UNSPEC) 76 { 77 warn_elem(e, "has no %s policy specified, defaulting to DROP", name); 78 *pol = FW3_FLAG_DROP; 79 } 80 else if (*pol > FW3_FLAG_DROP) 81 { 82 warn_elem(e, "has invalid %s policy, defaulting to DROP", name); 83 *pol = FW3_FLAG_DROP; 84 } 85 } 86 87 static void 88 check_target(struct uci_element *e, bool *available, const char *target, const bool ipv6) 89 { 90 const bool b = fw3_has_target(ipv6, target); 91 if (!b) 92 { 93 warn_elem(e, "requires unavailable target extension %s, disabling", target); 94 *available = false; 95 } 96 } 97 98 static void 99 check_any_reject_code(struct uci_element *e, enum fw3_reject_code *any_reject_code) 100 { 101 if (*any_reject_code == FW3_REJECT_CODE_TCP_RESET) { 102 warn_elem(e, "tcp-reset not valid for any_reject_code, defaulting to port-unreach"); 103 *any_reject_code = FW3_REJECT_CODE_PORT_UNREACH; 104 } 105 } 106 107 static const char* 108 get_reject_code(enum fw3_family family, enum fw3_reject_code reject_code) 109 { 110 switch (reject_code) { 111 case FW3_REJECT_CODE_TCP_RESET: 112 return "tcp-reset"; 113 case FW3_REJECT_CODE_PORT_UNREACH: 114 return "port-unreach"; 115 case FW3_REJECT_CODE_ADM_PROHIBITED: 116 return family == FW3_FAMILY_V6 ? "adm-prohibited": "admin-prohib"; 117 default: 118 return "unknown"; 119 } 120 } 121 122 void 123 fw3_load_defaults(struct fw3_state *state, struct uci_package *p) 124 { 125 struct uci_section *s; 126 struct uci_element *e; 127 struct fw3_defaults *defs = &state->defaults; 128 129 bool seen = false; 130 131 defs->tcp_reject_code = FW3_REJECT_CODE_TCP_RESET; 132 defs->any_reject_code = FW3_REJECT_CODE_PORT_UNREACH; 133 defs->syn_flood_rate.rate = 25; 134 defs->syn_flood_rate.burst = 50; 135 defs->tcp_syncookies = true; 136 defs->tcp_window_scaling = true; 137 defs->custom_chains = true; 138 defs->auto_helper = true; 139 140 uci_foreach_element(&p->sections, e) 141 { 142 s = uci_to_section(e); 143 144 if (strcmp(s->type, "defaults")) 145 continue; 146 147 if (seen) 148 { 149 warn_elem(e, "ignoring duplicate section"); 150 continue; 151 } 152 153 seen = true; 154 155 if(!fw3_parse_options(&state->defaults, fw3_flag_opts, s)) 156 warn_elem(e, "has invalid options"); 157 158 check_policy(e, &defs->policy_input, "input"); 159 check_policy(e, &defs->policy_output, "output"); 160 check_policy(e, &defs->policy_forward, "forward"); 161 162 check_any_reject_code(e, &defs->any_reject_code); 163 164 /* exists in both ipv4 and ipv6, if at all, so only check ipv4 */ 165 check_target(e, &defs->flow_offloading, "FLOWOFFLOAD", false); 166 } 167 } 168 169 void 170 fw3_print_default_chains(struct fw3_ipt_handle *handle, struct fw3_state *state, 171 bool reload) 172 { 173 struct fw3_defaults *defs = &state->defaults; 174 const struct fw3_chain_spec *c; 175 176 #define policy(t) \ 177 ((t == FW3_FLAG_REJECT) ? FW3_FLAG_DROP : t) 178 179 if (handle->family == FW3_FAMILY_V6 && defs->disable_ipv6) 180 return; 181 182 if (handle->table == FW3_TABLE_FILTER) 183 { 184 fw3_ipt_set_policy(handle, "INPUT", policy(defs->policy_input)); 185 fw3_ipt_set_policy(handle, "OUTPUT", policy(defs->policy_output)); 186 fw3_ipt_set_policy(handle, "FORWARD", policy(defs->policy_forward)); 187 } 188 189 if (defs->custom_chains) 190 set(defs->flags, handle->family, FW3_FLAG_CUSTOM_CHAINS); 191 192 if (defs->syn_flood) 193 set(defs->flags, handle->family, FW3_FLAG_SYN_FLOOD); 194 195 for (c = default_chains; c->format; c++) 196 { 197 if (!fw3_is_family(c, handle->family)) 198 continue; 199 200 if (c->table != handle->table) 201 continue; 202 203 if (c->flag && 204 !fw3_hasbit(defs->flags[handle->family == FW3_FAMILY_V6], c->flag)) 205 continue; 206 207 fw3_ipt_create_chain(handle, reload, c->format); 208 } 209 210 set(defs->flags, handle->family, handle->table); 211 } 212 213 void 214 fw3_print_default_head_rules(struct fw3_ipt_handle *handle, 215 struct fw3_state *state, bool reload) 216 { 217 int i; 218 struct fw3_defaults *defs = &state->defaults; 219 struct fw3_device lodev = { .set = true, .name = "lo" }; 220 struct fw3_protocol tcp = { .protocol = 6 }; 221 struct fw3_ipt_rule *r; 222 223 const char *chains[] = { 224 "INPUT", "input", 225 "OUTPUT", "output", 226 "FORWARD", "forwarding", 227 }; 228 229 switch (handle->table) 230 { 231 case FW3_TABLE_FILTER: 232 233 r = fw3_ipt_rule_create(handle, NULL, &lodev, NULL, NULL, NULL); 234 fw3_ipt_rule_target(r, "ACCEPT"); 235 fw3_ipt_rule_append(r, "INPUT"); 236 237 r = fw3_ipt_rule_create(handle, NULL, NULL, &lodev, NULL, NULL); 238 fw3_ipt_rule_target(r, "ACCEPT"); 239 fw3_ipt_rule_append(r, "OUTPUT"); 240 241 if (defs->custom_chains) 242 { 243 for (i = 0; i < ARRAY_SIZE(chains); i += 2) 244 { 245 r = fw3_ipt_rule_new(handle); 246 fw3_ipt_rule_comment(r, "Custom %s rule chain", chains[i+1]); 247 fw3_ipt_rule_target(r, "%s_rule", chains[i+1]); 248 fw3_ipt_rule_append(r, chains[i]); 249 } 250 } 251 252 if (defs->flow_offloading) 253 { 254 struct fw3_protocol any = {}; 255 256 r = fw3_ipt_rule_new(handle); 257 fw3_ipt_rule_proto(r, &any); 258 fw3_ipt_rule_comment(r, "Traffic offloading"); 259 fw3_ipt_rule_extra(r, "-m conntrack --ctstate RELATED,ESTABLISHED"); 260 fw3_ipt_rule_target(r, "FLOWOFFLOAD"); 261 if (defs->flow_offloading_hw) 262 fw3_ipt_rule_addarg(r, false, "--hw", NULL); 263 fw3_ipt_rule_append(r, "FORWARD"); 264 } 265 266 for (i = 0; i < ARRAY_SIZE(chains); i += 2) 267 { 268 r = fw3_ipt_rule_new(handle); 269 fw3_ipt_rule_extra(r, "-m conntrack --ctstate RELATED,ESTABLISHED"); 270 fw3_ipt_rule_target(r, "ACCEPT"); 271 fw3_ipt_rule_append(r, chains[i]); 272 273 if (defs->drop_invalid) 274 { 275 r = fw3_ipt_rule_new(handle); 276 fw3_ipt_rule_extra(r, "-m conntrack --ctstate INVALID"); 277 fw3_ipt_rule_target(r, "DROP"); 278 fw3_ipt_rule_append(r, chains[i]); 279 } 280 } 281 282 if (defs->syn_flood) 283 { 284 r = fw3_ipt_rule_create(handle, NULL, NULL, NULL, NULL, NULL); 285 fw3_ipt_rule_limit(r, &defs->syn_flood_rate); 286 fw3_ipt_rule_target(r, "RETURN"); 287 fw3_ipt_rule_append(r, "syn_flood"); 288 289 r = fw3_ipt_rule_new(handle); 290 fw3_ipt_rule_target(r, "DROP"); 291 fw3_ipt_rule_append(r, "syn_flood"); 292 293 r = fw3_ipt_rule_create(handle, &tcp, NULL, NULL, NULL, NULL); 294 fw3_ipt_rule_extra(r, "--syn"); 295 fw3_ipt_rule_target(r, "syn_flood"); 296 fw3_ipt_rule_append(r, "INPUT"); 297 } 298 299 r = fw3_ipt_rule_create(handle, &tcp, NULL, NULL, NULL, NULL); 300 fw3_ipt_rule_target(r, "REJECT"); 301 fw3_ipt_rule_addarg(r, false, "--reject-with", get_reject_code(handle->family, defs->tcp_reject_code)); 302 fw3_ipt_rule_append(r, "reject"); 303 304 r = fw3_ipt_rule_new(handle); 305 fw3_ipt_rule_target(r, "REJECT"); 306 fw3_ipt_rule_addarg(r, false, "--reject-with", get_reject_code(handle->family, defs->any_reject_code)); 307 fw3_ipt_rule_append(r, "reject"); 308 309 break; 310 311 case FW3_TABLE_NAT: 312 if (defs->custom_chains) 313 { 314 r = fw3_ipt_rule_new(handle); 315 fw3_ipt_rule_comment(r, "Custom prerouting rule chain"); 316 fw3_ipt_rule_target(r, "prerouting_rule"); 317 fw3_ipt_rule_append(r, "PREROUTING"); 318 319 r = fw3_ipt_rule_new(handle); 320 fw3_ipt_rule_comment(r, "Custom postrouting rule chain"); 321 fw3_ipt_rule_target(r, "postrouting_rule"); 322 fw3_ipt_rule_append(r, "POSTROUTING"); 323 } 324 break; 325 326 default: 327 break; 328 } 329 } 330 331 void 332 fw3_print_default_tail_rules(struct fw3_ipt_handle *handle, 333 struct fw3_state *state, bool reload) 334 { 335 struct fw3_defaults *defs = &state->defaults; 336 struct fw3_ipt_rule *r; 337 338 if (handle->table != FW3_TABLE_FILTER) 339 return; 340 341 if (defs->policy_input == FW3_FLAG_REJECT) 342 { 343 r = fw3_ipt_rule_new(handle); 344 345 if (!r) 346 return; 347 348 fw3_ipt_rule_target(r, "reject"); 349 fw3_ipt_rule_append(r, "INPUT"); 350 } 351 352 if (defs->policy_output == FW3_FLAG_REJECT) 353 { 354 r = fw3_ipt_rule_new(handle); 355 356 if (!r) 357 return; 358 359 fw3_ipt_rule_target(r, "reject"); 360 fw3_ipt_rule_append(r, "OUTPUT"); 361 } 362 363 if (defs->policy_forward == FW3_FLAG_REJECT) 364 { 365 r = fw3_ipt_rule_new(handle); 366 367 if (!r) 368 return; 369 370 fw3_ipt_rule_target(r, "reject"); 371 fw3_ipt_rule_append(r, "FORWARD"); 372 } 373 } 374 375 static void 376 set_default(const char *name, int set) 377 { 378 FILE *f; 379 char path[sizeof("/proc/sys/net/ipv4/tcp_window_scaling")]; 380 381 snprintf(path, sizeof(path), "/proc/sys/net/ipv4/tcp_%s", name); 382 383 info(" * Set tcp_%s to %s", name, set ? "on" : "off"); 384 385 if (!(f = fopen(path, "w"))) 386 { 387 info(" ! Unable to write value: %s", strerror(errno)); 388 return; 389 } 390 391 fprintf(f, "%u\n", set); 392 fclose(f); 393 } 394 395 void 396 fw3_set_defaults(struct fw3_state *state) 397 { 398 set_default("ecn", state->defaults.tcp_ecn); 399 set_default("syncookies", state->defaults.tcp_syncookies); 400 set_default("window_scaling", state->defaults.tcp_window_scaling); 401 } 402 403 void 404 fw3_flush_rules(struct fw3_ipt_handle *handle, struct fw3_state *state, 405 bool reload) 406 { 407 enum fw3_flag policy = reload ? FW3_FLAG_DROP : FW3_FLAG_ACCEPT; 408 struct fw3_defaults *defs = &state->defaults; 409 const struct fw3_chain_spec *c; 410 411 if (!has(defs->flags, handle->family, handle->table)) 412 return; 413 414 if (handle->table == FW3_TABLE_FILTER) 415 { 416 fw3_ipt_set_policy(handle, "INPUT", policy); 417 fw3_ipt_set_policy(handle, "OUTPUT", policy); 418 fw3_ipt_set_policy(handle, "FORWARD", policy); 419 } 420 421 fw3_ipt_delete_id_rules(handle, "INPUT"); 422 fw3_ipt_delete_id_rules(handle, "OUTPUT"); 423 fw3_ipt_delete_id_rules(handle, "FORWARD"); 424 fw3_ipt_delete_id_rules(handle, "PREROUTING"); 425 fw3_ipt_delete_id_rules(handle, "POSTROUTING"); 426 427 /* first flush all the rules ... */ 428 for (c = default_chains; c->format; c++) 429 { 430 /* don't touch user chains on selective stop */ 431 if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS) 432 continue; 433 434 if (!fw3_is_family(c, handle->family)) 435 continue; 436 437 if (c->table != handle->table) 438 continue; 439 440 if (c->flag && !has(defs->flags, handle->family, c->flag)) 441 continue; 442 443 fw3_ipt_flush_chain(handle, c->format); 444 } 445 446 /* ... then remove the chains */ 447 for (c = default_chains; c->format; c++) 448 { 449 if (!fw3_is_family(c, handle->family)) 450 continue; 451 452 if (c->table != handle->table) 453 continue; 454 455 if (c->flag && !has(defs->flags, handle->family, c->flag)) 456 continue; 457 458 fw3_ipt_delete_chain(handle, reload, c->format); 459 } 460 461 del(defs->flags, handle->family, handle->table); 462 } 463 464 void 465 fw3_flush_all(struct fw3_ipt_handle *handle) 466 { 467 if (handle->table == FW3_TABLE_FILTER) 468 { 469 fw3_ipt_set_policy(handle, "INPUT", FW3_FLAG_ACCEPT); 470 fw3_ipt_set_policy(handle, "OUTPUT", FW3_FLAG_ACCEPT); 471 fw3_ipt_set_policy(handle, "FORWARD", FW3_FLAG_ACCEPT); 472 } 473 474 fw3_ipt_flush(handle); 475 } 476
This page was automatically generated by LXR 0.3.1. • OpenWrt