zones.c 23 KB

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