zones.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  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. #include "zones.h"
  19. #include "ubus.h"
  20. #include "helpers.h"
  21. #define C(f, tbl, tgt, fmt) \
  22. { FW3_FAMILY_##f, FW3_TABLE_##tbl, FW3_FLAG_##tgt, fmt }
  23. static const struct fw3_chain_spec zone_chains[] = {
  24. C(ANY, FILTER, UNSPEC, "zone_?_input"),
  25. C(ANY, FILTER, UNSPEC, "zone_?_output"),
  26. C(ANY, FILTER, UNSPEC, "zone_?_forward"),
  27. C(ANY, FILTER, SRC_ACCEPT, "zone_?_src_ACCEPT"),
  28. C(ANY, FILTER, SRC_REJECT, "zone_?_src_REJECT"),
  29. C(ANY, FILTER, SRC_DROP, "zone_?_src_DROP"),
  30. C(ANY, FILTER, ACCEPT, "zone_?_dest_ACCEPT"),
  31. C(ANY, FILTER, REJECT, "zone_?_dest_REJECT"),
  32. C(ANY, FILTER, DROP, "zone_?_dest_DROP"),
  33. C(V4, NAT, SNAT, "zone_?_postrouting"),
  34. C(V4, NAT, DNAT, "zone_?_prerouting"),
  35. C(ANY, RAW, HELPER, "zone_?_helper"),
  36. C(ANY, RAW, NOTRACK, "zone_?_notrack"),
  37. C(ANY, FILTER, CUSTOM_CHAINS, "input_?_rule"),
  38. C(ANY, FILTER, CUSTOM_CHAINS, "output_?_rule"),
  39. C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_?_rule"),
  40. C(V4, NAT, CUSTOM_CHAINS, "prerouting_?_rule"),
  41. C(V4, NAT, CUSTOM_CHAINS, "postrouting_?_rule"),
  42. { }
  43. };
  44. enum fw3_zone_logmask {
  45. FW3_ZONE_LOG_FILTER = (1 << 0),
  46. FW3_ZONE_LOG_MANGLE = (1 << 1),
  47. };
  48. const struct fw3_option fw3_zone_opts[] = {
  49. FW3_OPT("enabled", bool, zone, enabled),
  50. FW3_OPT("name", string, zone, name),
  51. FW3_OPT("family", family, zone, family),
  52. FW3_LIST("network", device, zone, networks),
  53. FW3_LIST("device", device, zone, devices),
  54. FW3_LIST("subnet", network, zone, subnets),
  55. FW3_OPT("input", target, zone, policy_input),
  56. FW3_OPT("forward", target, zone, policy_forward),
  57. FW3_OPT("output", target, zone, policy_output),
  58. FW3_OPT("masq", bool, zone, masq),
  59. FW3_OPT("masq_allow_invalid", bool, zone, masq_allow_invalid),
  60. FW3_LIST("masq_src", network, zone, masq_src),
  61. FW3_LIST("masq_dest", network, zone, masq_dest),
  62. FW3_OPT("extra", string, zone, extra_src),
  63. FW3_OPT("extra_src", string, zone, extra_src),
  64. FW3_OPT("extra_dest", string, zone, extra_dest),
  65. FW3_OPT("mtu_fix", bool, zone, mtu_fix),
  66. FW3_OPT("custom_chains", bool, zone, custom_chains),
  67. FW3_OPT("log", int, zone, log),
  68. FW3_OPT("log_limit", limit, zone, log_limit),
  69. FW3_OPT("auto_helper", bool, zone, auto_helper),
  70. FW3_LIST("helper", cthelper, zone, cthelpers),
  71. FW3_OPT("__flags_v4", int, zone, flags[0]),
  72. FW3_OPT("__flags_v6", int, zone, flags[1]),
  73. FW3_LIST("__addrs", address, zone, old_addrs),
  74. { }
  75. };
  76. static void
  77. check_policy(struct uci_element *e, enum fw3_flag *pol, enum fw3_flag def,
  78. const char *name)
  79. {
  80. if (*pol == FW3_FLAG_UNSPEC)
  81. {
  82. warn_elem(e, "has no %s policy specified, using default", name);
  83. *pol = def;
  84. }
  85. else if (*pol > FW3_FLAG_DROP)
  86. {
  87. warn_elem(e, "has invalid %s policy, using default", name);
  88. *pol = def;
  89. }
  90. }
  91. static bool
  92. check_masq_addrs(struct list_head *head)
  93. {
  94. struct fw3_address *addr;
  95. int n_addr = 0, n_failed = 0;
  96. list_for_each_entry(addr, head, list)
  97. {
  98. if (addr->invert)
  99. continue;
  100. n_addr++;
  101. if (!addr->set && addr->resolved)
  102. n_failed++;
  103. }
  104. return (n_addr == 0 || n_failed < n_addr);
  105. }
  106. static void
  107. resolve_networks(struct uci_element *e, struct fw3_zone *zone)
  108. {
  109. struct fw3_device *net, *dev, *tmp;
  110. list_for_each_entry(net, &zone->networks, list)
  111. {
  112. tmp = fw3_ubus_device(net->name);
  113. if (!tmp)
  114. {
  115. warn_elem(e, "cannot resolve device of network '%s'", net->name);
  116. continue;
  117. }
  118. list_for_each_entry(dev, &zone->devices, list)
  119. if (!strcmp(dev->name, tmp->name))
  120. goto alias;
  121. snprintf(tmp->network, sizeof(tmp->network), "%s", net->name);
  122. list_add_tail(&tmp->list, &zone->devices);
  123. continue;
  124. alias:
  125. free(tmp);
  126. }
  127. }
  128. static void
  129. resolve_cthelpers(struct fw3_state *s, struct uci_element *e, struct fw3_zone *zone)
  130. {
  131. struct fw3_cthelpermatch *match;
  132. if (list_empty(&zone->cthelpers))
  133. {
  134. if (!zone->masq && zone->auto_helper)
  135. {
  136. fw3_setbit(zone->flags[0], FW3_FLAG_HELPER);
  137. fw3_setbit(zone->flags[1], FW3_FLAG_HELPER);
  138. }
  139. return;
  140. }
  141. list_for_each_entry(match, &zone->cthelpers, list)
  142. {
  143. if (match->invert)
  144. {
  145. warn_elem(e, "must not use a negated helper match");
  146. continue;
  147. }
  148. match->ptr = fw3_lookup_cthelper(s, match->name);
  149. if (!match->ptr)
  150. {
  151. warn_elem(e, "refers to not existing helper '%s'", match->name);
  152. continue;
  153. }
  154. if (fw3_is_family(match->ptr, FW3_FAMILY_V4))
  155. fw3_setbit(zone->flags[0], FW3_FLAG_HELPER);
  156. if (fw3_is_family(match->ptr, FW3_FAMILY_V6))
  157. fw3_setbit(zone->flags[1], FW3_FLAG_HELPER);
  158. }
  159. }
  160. struct fw3_zone *
  161. fw3_alloc_zone(void)
  162. {
  163. struct fw3_zone *zone;
  164. zone = calloc(1, sizeof(*zone));
  165. if (!zone)
  166. return NULL;
  167. INIT_LIST_HEAD(&zone->networks);
  168. INIT_LIST_HEAD(&zone->devices);
  169. INIT_LIST_HEAD(&zone->subnets);
  170. INIT_LIST_HEAD(&zone->masq_src);
  171. INIT_LIST_HEAD(&zone->masq_dest);
  172. INIT_LIST_HEAD(&zone->cthelpers);
  173. INIT_LIST_HEAD(&zone->old_addrs);
  174. zone->enabled = true;
  175. zone->auto_helper = true;
  176. zone->custom_chains = true;
  177. zone->log_limit.rate = 10;
  178. return zone;
  179. }
  180. void
  181. fw3_load_zones(struct fw3_state *state, struct uci_package *p)
  182. {
  183. struct uci_section *s;
  184. struct uci_element *e;
  185. struct fw3_zone *zone;
  186. struct fw3_defaults *defs = &state->defaults;
  187. INIT_LIST_HEAD(&state->zones);
  188. uci_foreach_element(&p->sections, e)
  189. {
  190. s = uci_to_section(e);
  191. if (strcmp(s->type, "zone"))
  192. continue;
  193. zone = fw3_alloc_zone();
  194. if (!zone)
  195. continue;
  196. if (!fw3_parse_options(zone, fw3_zone_opts, s))
  197. warn_elem(e, "has invalid options");
  198. if (!zone->enabled)
  199. {
  200. fw3_free_zone(zone);
  201. continue;
  202. }
  203. if (!zone->extra_dest)
  204. zone->extra_dest = zone->extra_src;
  205. if (!defs->custom_chains && zone->custom_chains)
  206. zone->custom_chains = false;
  207. if (!defs->auto_helper && zone->auto_helper)
  208. zone->auto_helper = false;
  209. if (!zone->name || !*zone->name)
  210. {
  211. warn_elem(e, "has no name - ignoring");
  212. fw3_free_zone(zone);
  213. continue;
  214. }
  215. if (strlen(zone->name) > FW3_ZONE_MAXNAMELEN)
  216. {
  217. warn_elem(e, "must not have a name longer than %u characters",
  218. FW3_ZONE_MAXNAMELEN);
  219. fw3_free_zone(zone);
  220. continue;
  221. }
  222. fw3_ubus_zone_devices(zone);
  223. if (list_empty(&zone->networks) && list_empty(&zone->devices) &&
  224. list_empty(&zone->subnets) && !zone->extra_src)
  225. {
  226. warn_elem(e, "has no device, network, subnet or extra options");
  227. }
  228. if (!check_masq_addrs(&zone->masq_src))
  229. {
  230. warn_elem(e, "has unresolved masq_src, disabling masq");
  231. zone->masq = false;
  232. }
  233. if (!check_masq_addrs(&zone->masq_dest))
  234. {
  235. warn_elem(e, "has unresolved masq_dest, disabling masq");
  236. zone->masq = false;
  237. }
  238. check_policy(e, &zone->policy_input, defs->policy_input, "input");
  239. check_policy(e, &zone->policy_output, defs->policy_output, "output");
  240. check_policy(e, &zone->policy_forward, defs->policy_forward, "forward");
  241. resolve_networks(e, zone);
  242. if (zone->masq)
  243. {
  244. fw3_setbit(zone->flags[0], FW3_FLAG_SNAT);
  245. }
  246. if (zone->custom_chains)
  247. {
  248. fw3_setbit(zone->flags[0], FW3_FLAG_SNAT);
  249. fw3_setbit(zone->flags[0], FW3_FLAG_DNAT);
  250. }
  251. resolve_cthelpers(state, e, zone);
  252. fw3_setbit(zone->flags[0], fw3_to_src_target(zone->policy_input));
  253. fw3_setbit(zone->flags[0], zone->policy_forward);
  254. fw3_setbit(zone->flags[0], zone->policy_output);
  255. fw3_setbit(zone->flags[1], fw3_to_src_target(zone->policy_input));
  256. fw3_setbit(zone->flags[1], zone->policy_forward);
  257. fw3_setbit(zone->flags[1], zone->policy_output);
  258. list_add_tail(&zone->list, &state->zones);
  259. }
  260. }
  261. static char *
  262. format_chain(const char *fmt, const char *zonename)
  263. {
  264. static char chain[32];
  265. size_t rem;
  266. char *p;
  267. int len;
  268. for (p = chain, rem = sizeof(chain); *fmt; fmt++) {
  269. if (*fmt == '?') {
  270. len = snprintf(p, rem, "%s", zonename);
  271. if (len < 0 || len >= rem)
  272. break;
  273. rem -= len;
  274. p += len;
  275. }
  276. else {
  277. if (rem <= 1)
  278. break;
  279. *p++ = *fmt;
  280. rem--;
  281. }
  282. }
  283. *p = 0;
  284. return chain;
  285. }
  286. static void
  287. print_zone_chain(struct fw3_ipt_handle *handle, struct fw3_state *state,
  288. bool reload, struct fw3_zone *zone)
  289. {
  290. int i;
  291. struct fw3_ipt_rule *r;
  292. const struct fw3_chain_spec *c;
  293. const char *flt_chains[] = {
  294. "input", "input",
  295. "output", "output",
  296. "forward", "forwarding",
  297. };
  298. const char *nat_chains[] = {
  299. "prerouting", "prerouting",
  300. "postrouting", "postrouting",
  301. };
  302. if (!fw3_is_family(zone, handle->family))
  303. return;
  304. set(zone->flags, handle->family, handle->table);
  305. if (zone->custom_chains)
  306. set(zone->flags, handle->family, FW3_FLAG_CUSTOM_CHAINS);
  307. for (c = zone_chains; c->format; c++)
  308. {
  309. if (!fw3_is_family(c, handle->family))
  310. continue;
  311. if (c->table != handle->table)
  312. continue;
  313. if (c->flag &&
  314. !fw3_hasbit(zone->flags[handle->family == FW3_FAMILY_V6], c->flag))
  315. continue;
  316. fw3_ipt_create_chain(handle, reload, format_chain(c->format, zone->name));
  317. }
  318. if (zone->custom_chains)
  319. {
  320. if (handle->table == FW3_TABLE_FILTER)
  321. {
  322. for (i = 0; i < sizeof(flt_chains)/sizeof(flt_chains[0]); i += 2)
  323. {
  324. r = fw3_ipt_rule_new(handle);
  325. fw3_ipt_rule_comment(r, "Custom %s %s rule chain", zone->name, flt_chains[i+1]);
  326. fw3_ipt_rule_target(r, "%s_%s_rule", flt_chains[i+1], zone->name);
  327. fw3_ipt_rule_append(r, "zone_%s_%s", zone->name, flt_chains[i]);
  328. }
  329. }
  330. else if (handle->table == FW3_TABLE_NAT)
  331. {
  332. for (i = 0; i < sizeof(nat_chains)/sizeof(nat_chains[0]); i += 2)
  333. {
  334. r = fw3_ipt_rule_new(handle);
  335. fw3_ipt_rule_comment(r, "Custom %s %s rule chain", zone->name, nat_chains[i+1]);
  336. fw3_ipt_rule_target(r, "%s_%s_rule", nat_chains[i+1], zone->name);
  337. fw3_ipt_rule_append(r, "zone_%s_%s", zone->name, nat_chains[i]);
  338. }
  339. }
  340. }
  341. set(zone->flags, handle->family, handle->table);
  342. }
  343. static void
  344. print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
  345. bool reload, struct fw3_zone *zone,
  346. struct fw3_device *dev, struct fw3_address *sub)
  347. {
  348. struct fw3_protocol tcp = { .protocol = 6 };
  349. struct fw3_ipt_rule *r;
  350. enum fw3_flag t;
  351. char buf[32];
  352. int i;
  353. const char *chains[] = {
  354. "input", "INPUT",
  355. "output", "OUTPUT",
  356. "forward", "FORWARD",
  357. };
  358. #define jump_target(t) \
  359. ((t == FW3_FLAG_REJECT) ? "reject" : fw3_flag_names[t])
  360. if (handle->table == FW3_TABLE_FILTER)
  361. {
  362. for (t = FW3_FLAG_ACCEPT; t <= FW3_FLAG_DROP; t++)
  363. {
  364. if (t > FW3_FLAG_ACCEPT && zone->log & FW3_ZONE_LOG_FILTER)
  365. {
  366. if (has(zone->flags, handle->family, fw3_to_src_target(t)))
  367. {
  368. r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL);
  369. snprintf(buf, sizeof(buf) - 1, "%s %s in: ",
  370. fw3_flag_names[t], zone->name);
  371. fw3_ipt_rule_limit(r, &zone->log_limit);
  372. fw3_ipt_rule_target(r, "LOG");
  373. fw3_ipt_rule_addarg(r, false, "--log-prefix", buf);
  374. fw3_ipt_rule_replace(r, "zone_%s_src_%s",
  375. zone->name, fw3_flag_names[t]);
  376. }
  377. if (has(zone->flags, handle->family, t))
  378. {
  379. r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub);
  380. snprintf(buf, sizeof(buf) - 1, "%s %s out: ",
  381. fw3_flag_names[t], zone->name);
  382. fw3_ipt_rule_limit(r, &zone->log_limit);
  383. fw3_ipt_rule_target(r, "LOG");
  384. fw3_ipt_rule_addarg(r, false, "--log-prefix", buf);
  385. fw3_ipt_rule_replace(r, "zone_%s_dest_%s",
  386. zone->name, fw3_flag_names[t]);
  387. }
  388. }
  389. if (has(zone->flags, handle->family, fw3_to_src_target(t)))
  390. {
  391. r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL);
  392. fw3_ipt_rule_target(r, jump_target(t));
  393. fw3_ipt_rule_extra(r, zone->extra_src);
  394. if (t == FW3_FLAG_ACCEPT && !state->defaults.drop_invalid)
  395. fw3_ipt_rule_extra(r,
  396. "-m conntrack --ctstate NEW,UNTRACKED");
  397. fw3_ipt_rule_replace(r, "zone_%s_src_%s", zone->name,
  398. fw3_flag_names[t]);
  399. }
  400. if (has(zone->flags, handle->family, t))
  401. {
  402. if (t == FW3_FLAG_ACCEPT &&
  403. zone->masq && !zone->masq_allow_invalid)
  404. {
  405. r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub);
  406. fw3_ipt_rule_extra(r, "-m conntrack --ctstate INVALID");
  407. fw3_ipt_rule_comment(r, "Prevent NAT leakage");
  408. fw3_ipt_rule_target(r, fw3_flag_names[FW3_FLAG_DROP]);
  409. fw3_ipt_rule_replace(r, "zone_%s_dest_%s", zone->name,
  410. fw3_flag_names[t]);
  411. }
  412. r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub);
  413. fw3_ipt_rule_target(r, jump_target(t));
  414. fw3_ipt_rule_extra(r, zone->extra_dest);
  415. fw3_ipt_rule_replace(r, "zone_%s_dest_%s", zone->name,
  416. fw3_flag_names[t]);
  417. }
  418. }
  419. for (i = 0; i < sizeof(chains)/sizeof(chains[0]); i += 2)
  420. {
  421. if (*chains[i] == 'o')
  422. r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub);
  423. else
  424. r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL);
  425. fw3_ipt_rule_target(r, "zone_%s_%s", zone->name, chains[i]);
  426. if (*chains[i] == 'o')
  427. fw3_ipt_rule_extra(r, zone->extra_dest);
  428. else
  429. fw3_ipt_rule_extra(r, zone->extra_src);
  430. fw3_ipt_rule_replace(r, chains[i + 1]);
  431. }
  432. }
  433. else if (handle->table == FW3_TABLE_NAT)
  434. {
  435. if (has(zone->flags, handle->family, FW3_FLAG_DNAT))
  436. {
  437. r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL);
  438. fw3_ipt_rule_target(r, "zone_%s_prerouting", zone->name);
  439. fw3_ipt_rule_extra(r, zone->extra_src);
  440. fw3_ipt_rule_replace(r, "PREROUTING");
  441. }
  442. if (has(zone->flags, handle->family, FW3_FLAG_SNAT))
  443. {
  444. r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub);
  445. fw3_ipt_rule_target(r, "zone_%s_postrouting", zone->name);
  446. fw3_ipt_rule_extra(r, zone->extra_dest);
  447. fw3_ipt_rule_replace(r, "POSTROUTING");
  448. }
  449. }
  450. else if (handle->table == FW3_TABLE_MANGLE)
  451. {
  452. if (zone->mtu_fix)
  453. {
  454. if (zone->log & FW3_ZONE_LOG_MANGLE)
  455. {
  456. snprintf(buf, sizeof(buf) - 1, "MSSFIX %s out: ", zone->name);
  457. r = fw3_ipt_rule_create(handle, &tcp, NULL, dev, NULL, sub);
  458. fw3_ipt_rule_addarg(r, false, "--tcp-flags", "SYN,RST");
  459. fw3_ipt_rule_addarg(r, false, "SYN", NULL);
  460. fw3_ipt_rule_limit(r, &zone->log_limit);
  461. fw3_ipt_rule_comment(r, "Zone %s MTU fix logging", zone->name);
  462. fw3_ipt_rule_target(r, "LOG");
  463. fw3_ipt_rule_addarg(r, false, "--log-prefix", buf);
  464. fw3_ipt_rule_replace(r, "FORWARD");
  465. }
  466. r = fw3_ipt_rule_create(handle, &tcp, NULL, dev, NULL, sub);
  467. fw3_ipt_rule_addarg(r, false, "--tcp-flags", "SYN,RST");
  468. fw3_ipt_rule_addarg(r, false, "SYN", NULL);
  469. fw3_ipt_rule_comment(r, "Zone %s MTU fixing", zone->name);
  470. fw3_ipt_rule_target(r, "TCPMSS");
  471. fw3_ipt_rule_addarg(r, false, "--clamp-mss-to-pmtu", NULL);
  472. fw3_ipt_rule_replace(r, "FORWARD");
  473. r = fw3_ipt_rule_create(handle, &tcp, dev, NULL, sub, NULL);
  474. fw3_ipt_rule_addarg(r, false, "--tcp-flags", "SYN,RST");
  475. fw3_ipt_rule_addarg(r, false, "SYN", NULL);
  476. fw3_ipt_rule_comment(r, "Zone %s MTU fixing", zone->name);
  477. fw3_ipt_rule_target(r, "TCPMSS");
  478. fw3_ipt_rule_addarg(r, false, "--clamp-mss-to-pmtu", NULL);
  479. fw3_ipt_rule_replace(r, "FORWARD");
  480. }
  481. }
  482. else if (handle->table == FW3_TABLE_RAW)
  483. {
  484. bool loopback_dev = (dev != NULL && !dev->any &&
  485. !dev->invert && fw3_check_loopback_dev(dev->name));
  486. char *chain = loopback_dev || (sub != NULL && !sub->invert && fw3_check_loopback_addr(sub)) ?
  487. "OUTPUT" : "PREROUTING";
  488. if (has(zone->flags, handle->family, FW3_FLAG_HELPER))
  489. {
  490. r = fw3_ipt_rule_create(handle, NULL, loopback_dev ? NULL : dev, NULL, sub, NULL);
  491. fw3_ipt_rule_comment(r, "%s CT helper assignment", zone->name);
  492. fw3_ipt_rule_target(r, "zone_%s_helper", zone->name);
  493. fw3_ipt_rule_extra(r, zone->extra_src);
  494. fw3_ipt_rule_replace(r, chain);
  495. }
  496. if (has(zone->flags, handle->family, FW3_FLAG_NOTRACK))
  497. {
  498. r = fw3_ipt_rule_create(handle, NULL, loopback_dev ? NULL : dev, NULL, sub, NULL);
  499. fw3_ipt_rule_comment(r, "%s CT bypass", zone->name);
  500. fw3_ipt_rule_target(r, "zone_%s_notrack", zone->name);
  501. fw3_ipt_rule_extra(r, zone->extra_src);
  502. fw3_ipt_rule_replace(r, chain);
  503. }
  504. }
  505. }
  506. static void
  507. print_interface_rules(struct fw3_ipt_handle *handle, struct fw3_state *state,
  508. bool reload, struct fw3_zone *zone)
  509. {
  510. struct fw3_device *dev;
  511. struct fw3_address *sub;
  512. fw3_foreach(dev, &zone->devices)
  513. fw3_foreach(sub, &zone->subnets)
  514. {
  515. if (!fw3_is_family(sub, handle->family))
  516. continue;
  517. if (!dev && !sub && !zone->extra_src && !zone->extra_dest)
  518. continue;
  519. print_interface_rule(handle, state, reload, zone, dev, sub);
  520. }
  521. }
  522. static struct fw3_address *
  523. next_addr(struct fw3_address *addr, struct list_head *list,
  524. enum fw3_family family, bool invert)
  525. {
  526. struct list_head *p;
  527. struct fw3_address *rv;
  528. for (p = addr ? addr->list.next : list->next; p != list; p = p->next)
  529. {
  530. rv = list_entry(p, struct fw3_address, list);
  531. if (fw3_is_family(rv, family) && rv->set && rv->invert == invert)
  532. return rv;
  533. }
  534. return NULL;
  535. }
  536. static void
  537. print_zone_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
  538. bool reload, struct fw3_zone *zone)
  539. {
  540. bool first_src, first_dest;
  541. struct fw3_address *msrc;
  542. struct fw3_address *mdest;
  543. struct fw3_ipt_rule *r;
  544. if (!fw3_is_family(zone, handle->family))
  545. return;
  546. info(" * Zone '%s'", zone->name);
  547. switch (handle->table)
  548. {
  549. case FW3_TABLE_FILTER:
  550. if (has(zone->flags, handle->family, FW3_FLAG_DNAT))
  551. {
  552. r = fw3_ipt_rule_new(handle);
  553. fw3_ipt_rule_extra(r, "-m conntrack --ctstate DNAT");
  554. fw3_ipt_rule_comment(r, "Accept port redirections");
  555. fw3_ipt_rule_target(r, fw3_flag_names[FW3_FLAG_ACCEPT]);
  556. fw3_ipt_rule_append(r, "zone_%s_input", zone->name);
  557. r = fw3_ipt_rule_new(handle);
  558. fw3_ipt_rule_extra(r, "-m conntrack --ctstate DNAT");
  559. fw3_ipt_rule_comment(r, "Accept port forwards");
  560. fw3_ipt_rule_target(r, fw3_flag_names[FW3_FLAG_ACCEPT]);
  561. fw3_ipt_rule_append(r, "zone_%s_forward", zone->name);
  562. }
  563. r = fw3_ipt_rule_new(handle);
  564. fw3_ipt_rule_target(r, "zone_%s_src_%s", zone->name,
  565. fw3_flag_names[zone->policy_input]);
  566. fw3_ipt_rule_append(r, "zone_%s_input", zone->name);
  567. r = fw3_ipt_rule_new(handle);
  568. fw3_ipt_rule_target(r, "zone_%s_dest_%s", zone->name,
  569. fw3_flag_names[zone->policy_forward]);
  570. fw3_ipt_rule_append(r, "zone_%s_forward", zone->name);
  571. r = fw3_ipt_rule_new(handle);
  572. fw3_ipt_rule_target(r, "zone_%s_dest_%s", zone->name,
  573. fw3_flag_names[zone->policy_output]);
  574. fw3_ipt_rule_append(r, "zone_%s_output", zone->name);
  575. break;
  576. case FW3_TABLE_NAT:
  577. if (zone->masq && handle->family == FW3_FAMILY_V4)
  578. {
  579. /* for any negated masq_src ip, emit -s addr -j RETURN rules */
  580. for (msrc = NULL;
  581. (msrc = next_addr(msrc, &zone->masq_src,
  582. handle->family, true)) != NULL; )
  583. {
  584. msrc->invert = false;
  585. r = fw3_ipt_rule_new(handle);
  586. fw3_ipt_rule_src_dest(r, msrc, NULL);
  587. fw3_ipt_rule_target(r, "RETURN");
  588. fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name);
  589. msrc->invert = true;
  590. }
  591. /* for any negated masq_dest ip, emit -d addr -j RETURN rules */
  592. for (mdest = NULL;
  593. (mdest = next_addr(mdest, &zone->masq_dest,
  594. handle->family, true)) != NULL; )
  595. {
  596. mdest->invert = false;
  597. r = fw3_ipt_rule_new(handle);
  598. fw3_ipt_rule_src_dest(r, NULL, mdest);
  599. fw3_ipt_rule_target(r, "RETURN");
  600. fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name);
  601. mdest->invert = true;
  602. }
  603. /* emit masquerading entries for non-negated addresses
  604. and ensure that both src and dest loops run at least once,
  605. even if there are no relevant addresses */
  606. for (first_src = true, msrc = NULL;
  607. (msrc = next_addr(msrc, &zone->masq_src,
  608. handle->family, false)) || first_src;
  609. first_src = false)
  610. {
  611. for (first_dest = true, mdest = NULL;
  612. (mdest = next_addr(mdest, &zone->masq_dest,
  613. handle->family, false)) || first_dest;
  614. first_dest = false)
  615. {
  616. r = fw3_ipt_rule_new(handle);
  617. fw3_ipt_rule_src_dest(r, msrc, mdest);
  618. fw3_ipt_rule_target(r, "MASQUERADE");
  619. fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name);
  620. }
  621. }
  622. }
  623. break;
  624. case FW3_TABLE_RAW:
  625. fw3_print_cthelpers(handle, state, zone);
  626. break;
  627. case FW3_TABLE_MANGLE:
  628. break;
  629. }
  630. print_interface_rules(handle, state, reload, zone);
  631. }
  632. void
  633. fw3_print_zone_chains(struct fw3_ipt_handle *handle, struct fw3_state *state,
  634. bool reload)
  635. {
  636. struct fw3_zone *zone;
  637. list_for_each_entry(zone, &state->zones, list)
  638. print_zone_chain(handle, state, reload, zone);
  639. }
  640. void
  641. fw3_print_zone_rules(struct fw3_ipt_handle *handle, struct fw3_state *state,
  642. bool reload)
  643. {
  644. struct fw3_zone *zone;
  645. list_for_each_entry(zone, &state->zones, list)
  646. print_zone_rule(handle, state, reload, zone);
  647. }
  648. void
  649. fw3_flush_zones(struct fw3_ipt_handle *handle, struct fw3_state *state,
  650. bool reload)
  651. {
  652. struct fw3_zone *z, *tmp;
  653. const struct fw3_chain_spec *c;
  654. list_for_each_entry_safe(z, tmp, &state->zones, list)
  655. {
  656. if (!has(z->flags, handle->family, handle->table))
  657. continue;
  658. /* first flush all rules ... */
  659. for (c = zone_chains; c->format; c++)
  660. {
  661. /* don't touch user chains on selective stop */
  662. if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS)
  663. continue;
  664. if (!fw3_is_family(c, handle->family))
  665. continue;
  666. if (c->table != handle->table)
  667. continue;
  668. if (c->flag && !has(z->flags, handle->family, c->flag))
  669. continue;
  670. fw3_ipt_flush_chain(handle, format_chain(c->format, z->name));
  671. }
  672. /* ... then remove the chains */
  673. for (c = zone_chains; c->format; c++)
  674. {
  675. if (!fw3_is_family(c, handle->family))
  676. continue;
  677. if (c->table != handle->table)
  678. continue;
  679. if (c->flag && !has(z->flags, handle->family, c->flag))
  680. continue;
  681. fw3_ipt_delete_chain(handle, reload,
  682. format_chain(c->format, z->name));
  683. }
  684. del(z->flags, handle->family, handle->table);
  685. }
  686. }
  687. void
  688. fw3_hotplug_zones(struct fw3_state *state, bool add)
  689. {
  690. struct fw3_zone *z;
  691. struct fw3_device *d;
  692. list_for_each_entry(z, &state->zones, list)
  693. {
  694. if (add != fw3_hasbit(z->flags[0], FW3_FLAG_HOTPLUG))
  695. {
  696. list_for_each_entry(d, &z->devices, list)
  697. fw3_hotplug(add, z, d);
  698. if (add)
  699. fw3_setbit(z->flags[0], FW3_FLAG_HOTPLUG);
  700. else
  701. fw3_delbit(z->flags[0], FW3_FLAG_HOTPLUG);
  702. }
  703. }
  704. }
  705. struct fw3_zone *
  706. fw3_lookup_zone(struct fw3_state *state, const char *name)
  707. {
  708. struct fw3_zone *z;
  709. if (list_empty(&state->zones))
  710. return NULL;
  711. list_for_each_entry(z, &state->zones, list)
  712. {
  713. if (strcmp(z->name, name))
  714. continue;
  715. return z;
  716. }
  717. return NULL;
  718. }
  719. struct list_head *
  720. fw3_resolve_zone_addresses(struct fw3_zone *zone, struct fw3_address *addr)
  721. {
  722. struct fw3_device *net;
  723. struct fw3_address *cur, *tmp;
  724. struct list_head *all;
  725. all = calloc(1, sizeof(*all));
  726. if (!all)
  727. return NULL;
  728. INIT_LIST_HEAD(all);
  729. if (addr && addr->set)
  730. {
  731. tmp = malloc(sizeof(*tmp));
  732. if (tmp)
  733. {
  734. *tmp = *addr;
  735. list_add_tail(&tmp->list, all);
  736. }
  737. }
  738. else
  739. {
  740. list_for_each_entry(net, &zone->networks, list)
  741. fw3_ubus_address(all, net->name);
  742. list_for_each_entry(cur, &zone->subnets, list)
  743. {
  744. tmp = malloc(sizeof(*tmp));
  745. if (!tmp)
  746. continue;
  747. *tmp = *cur;
  748. list_add_tail(&tmp->list, all);
  749. }
  750. }
  751. return all;
  752. }