defaults.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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 "defaults.h"
  19. #define C(f, tbl, def, fmt) \
  20. { FW3_FAMILY_##f, FW3_TABLE_##tbl, FW3_FLAG_##def, fmt }
  21. static const struct fw3_chain_spec default_chains[] = {
  22. C(ANY, FILTER, UNSPEC, "reject"),
  23. C(ANY, FILTER, CUSTOM_CHAINS, "input_rule"),
  24. C(ANY, FILTER, CUSTOM_CHAINS, "output_rule"),
  25. C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_rule"),
  26. C(ANY, FILTER, SYN_FLOOD, "syn_flood"),
  27. C(V4, NAT, CUSTOM_CHAINS, "prerouting_rule"),
  28. C(V4, NAT, CUSTOM_CHAINS, "postrouting_rule"),
  29. { }
  30. };
  31. const struct fw3_option fw3_flag_opts[] = {
  32. FW3_OPT("input", target, defaults, policy_input),
  33. FW3_OPT("forward", target, defaults, policy_forward),
  34. FW3_OPT("output", target, defaults, policy_output),
  35. FW3_OPT("drop_invalid", bool, defaults, drop_invalid),
  36. FW3_OPT("syn_flood", bool, defaults, syn_flood),
  37. FW3_OPT("synflood_protect", bool, defaults, syn_flood),
  38. FW3_OPT("synflood_rate", limit, defaults, syn_flood_rate),
  39. FW3_OPT("synflood_burst", int, defaults, syn_flood_rate.burst),
  40. FW3_OPT("tcp_syncookies", bool, defaults, tcp_syncookies),
  41. FW3_OPT("tcp_ecn", int, defaults, tcp_ecn),
  42. FW3_OPT("tcp_window_scaling", bool, defaults, tcp_window_scaling),
  43. FW3_OPT("accept_redirects", bool, defaults, accept_redirects),
  44. FW3_OPT("accept_source_route", bool, defaults, accept_source_route),
  45. FW3_OPT("auto_helper", bool, defaults, auto_helper),
  46. FW3_OPT("custom_chains", bool, defaults, custom_chains),
  47. FW3_OPT("disable_ipv6", bool, defaults, disable_ipv6),
  48. FW3_OPT("__flags_v4", int, defaults, flags[0]),
  49. FW3_OPT("__flags_v6", int, defaults, flags[1]),
  50. { }
  51. };
  52. static void
  53. check_policy(struct uci_element *e, enum fw3_flag *pol, const char *name)
  54. {
  55. if (*pol == FW3_FLAG_UNSPEC)
  56. {
  57. warn_elem(e, "has no %s policy specified, defaulting to DROP", name);
  58. *pol = FW3_FLAG_DROP;
  59. }
  60. else if (*pol > FW3_FLAG_DROP)
  61. {
  62. warn_elem(e, "has invalid %s policy, defaulting to DROP", name);
  63. *pol = FW3_FLAG_DROP;
  64. }
  65. }
  66. void
  67. fw3_load_defaults(struct fw3_state *state, struct uci_package *p)
  68. {
  69. struct uci_section *s;
  70. struct uci_element *e;
  71. struct fw3_defaults *defs = &state->defaults;
  72. bool seen = false;
  73. defs->syn_flood_rate.rate = 25;
  74. defs->syn_flood_rate.burst = 50;
  75. defs->tcp_syncookies = true;
  76. defs->tcp_window_scaling = true;
  77. defs->custom_chains = true;
  78. defs->auto_helper = true;
  79. uci_foreach_element(&p->sections, e)
  80. {
  81. s = uci_to_section(e);
  82. if (strcmp(s->type, "defaults"))
  83. continue;
  84. if (seen)
  85. {
  86. warn_elem(e, "ignoring duplicate section");
  87. continue;
  88. }
  89. if(!fw3_parse_options(&state->defaults, fw3_flag_opts, s))
  90. warn_elem(e, "has invalid options");
  91. check_policy(e, &defs->policy_input, "input");
  92. check_policy(e, &defs->policy_output, "output");
  93. check_policy(e, &defs->policy_forward, "forward");
  94. }
  95. }
  96. void
  97. fw3_print_default_chains(struct fw3_ipt_handle *handle, struct fw3_state *state,
  98. bool reload)
  99. {
  100. struct fw3_defaults *defs = &state->defaults;
  101. const struct fw3_chain_spec *c;
  102. #define policy(t) \
  103. ((t == FW3_FLAG_REJECT) ? FW3_FLAG_DROP : t)
  104. if (handle->family == FW3_FAMILY_V6 && defs->disable_ipv6)
  105. return;
  106. if (handle->table == FW3_TABLE_FILTER)
  107. {
  108. fw3_ipt_set_policy(handle, "INPUT", policy(defs->policy_input));
  109. fw3_ipt_set_policy(handle, "OUTPUT", policy(defs->policy_output));
  110. fw3_ipt_set_policy(handle, "FORWARD", policy(defs->policy_forward));
  111. }
  112. if (defs->custom_chains)
  113. set(defs->flags, handle->family, FW3_FLAG_CUSTOM_CHAINS);
  114. if (defs->syn_flood)
  115. set(defs->flags, handle->family, FW3_FLAG_SYN_FLOOD);
  116. for (c = default_chains; c->format; c++)
  117. {
  118. /* don't touch user chains on selective stop */
  119. if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS)
  120. continue;
  121. if (!fw3_is_family(c, handle->family))
  122. continue;
  123. if (c->table != handle->table)
  124. continue;
  125. if (c->flag &&
  126. !fw3_hasbit(defs->flags[handle->family == FW3_FAMILY_V6], c->flag))
  127. continue;
  128. fw3_ipt_create_chain(handle, c->format);
  129. }
  130. set(defs->flags, handle->family, handle->table);
  131. }
  132. void
  133. fw3_print_default_head_rules(struct fw3_ipt_handle *handle,
  134. struct fw3_state *state, bool reload)
  135. {
  136. int i;
  137. struct fw3_defaults *defs = &state->defaults;
  138. struct fw3_device lodev = { .set = true };
  139. struct fw3_protocol tcp = { .protocol = 6 };
  140. struct fw3_ipt_rule *r;
  141. const char *chains[] = {
  142. "INPUT", "input",
  143. "OUTPUT", "output",
  144. "FORWARD", "forwarding",
  145. };
  146. switch (handle->table)
  147. {
  148. case FW3_TABLE_FILTER:
  149. sprintf(lodev.name, "lo");
  150. r = fw3_ipt_rule_create(handle, NULL, &lodev, NULL, NULL, NULL);
  151. fw3_ipt_rule_target(r, "ACCEPT");
  152. fw3_ipt_rule_append(r, "INPUT");
  153. r = fw3_ipt_rule_create(handle, NULL, NULL, &lodev, NULL, NULL);
  154. fw3_ipt_rule_target(r, "ACCEPT");
  155. fw3_ipt_rule_append(r, "OUTPUT");
  156. if (defs->custom_chains)
  157. {
  158. for (i = 0; i < ARRAY_SIZE(chains); i += 2)
  159. {
  160. r = fw3_ipt_rule_new(handle);
  161. fw3_ipt_rule_comment(r, "user chain for %s", chains[i+1]);
  162. fw3_ipt_rule_target(r, "%s_rule", chains[i+1]);
  163. fw3_ipt_rule_append(r, chains[i]);
  164. }
  165. }
  166. for (i = 0; i < ARRAY_SIZE(chains); i += 2)
  167. {
  168. r = fw3_ipt_rule_new(handle);
  169. fw3_ipt_rule_extra(r, "-m conntrack --ctstate RELATED,ESTABLISHED");
  170. fw3_ipt_rule_target(r, "ACCEPT");
  171. fw3_ipt_rule_append(r, chains[i]);
  172. if (defs->drop_invalid)
  173. {
  174. r = fw3_ipt_rule_new(handle);
  175. fw3_ipt_rule_extra(r, "-m conntrack --ctstate INVALID");
  176. fw3_ipt_rule_target(r, "DROP");
  177. fw3_ipt_rule_append(r, chains[i]);
  178. }
  179. }
  180. if (defs->syn_flood)
  181. {
  182. r = fw3_ipt_rule_create(handle, &tcp, NULL, NULL, NULL, NULL);
  183. fw3_ipt_rule_extra(r, "--syn");
  184. fw3_ipt_rule_limit(r, &defs->syn_flood_rate);
  185. fw3_ipt_rule_target(r, "RETURN");
  186. fw3_ipt_rule_append(r, "syn_flood");
  187. r = fw3_ipt_rule_new(handle);
  188. fw3_ipt_rule_target(r, "DROP");
  189. fw3_ipt_rule_append(r, "syn_flood");
  190. r = fw3_ipt_rule_create(handle, &tcp, NULL, NULL, NULL, NULL);
  191. fw3_ipt_rule_extra(r, "--syn");
  192. fw3_ipt_rule_target(r, "syn_flood");
  193. fw3_ipt_rule_append(r, "INPUT");
  194. }
  195. r = fw3_ipt_rule_create(handle, &tcp, NULL, NULL, NULL, NULL);
  196. fw3_ipt_rule_target(r, "REJECT");
  197. fw3_ipt_rule_addarg(r, false, "--reject-with", "tcp-reset");
  198. fw3_ipt_rule_append(r, "reject");
  199. r = fw3_ipt_rule_new(handle);
  200. fw3_ipt_rule_target(r, "REJECT");
  201. fw3_ipt_rule_addarg(r, false, "--reject-with", "port-unreach");
  202. fw3_ipt_rule_append(r, "reject");
  203. break;
  204. case FW3_TABLE_NAT:
  205. if (defs->custom_chains)
  206. {
  207. r = fw3_ipt_rule_new(handle);
  208. fw3_ipt_rule_comment(r, "user chain for prerouting");
  209. fw3_ipt_rule_target(r, "prerouting_rule");
  210. fw3_ipt_rule_append(r, "PREROUTING");
  211. r = fw3_ipt_rule_new(handle);
  212. fw3_ipt_rule_comment(r, "user chain for postrouting");
  213. fw3_ipt_rule_target(r, "postrouting_rule");
  214. fw3_ipt_rule_append(r, "POSTROUTING");
  215. }
  216. break;
  217. default:
  218. break;
  219. }
  220. }
  221. void
  222. fw3_print_default_tail_rules(struct fw3_ipt_handle *handle,
  223. struct fw3_state *state, bool reload)
  224. {
  225. struct fw3_defaults *defs = &state->defaults;
  226. struct fw3_ipt_rule *r;
  227. if (handle->table != FW3_TABLE_FILTER)
  228. return;
  229. if (defs->policy_input == FW3_FLAG_REJECT)
  230. {
  231. r = fw3_ipt_rule_new(handle);
  232. if (!r)
  233. return;
  234. fw3_ipt_rule_target(r, "reject");
  235. fw3_ipt_rule_append(r, "INPUT");
  236. }
  237. if (defs->policy_output == FW3_FLAG_REJECT)
  238. {
  239. r = fw3_ipt_rule_new(handle);
  240. if (!r)
  241. return;
  242. fw3_ipt_rule_target(r, "reject");
  243. fw3_ipt_rule_append(r, "OUTPUT");
  244. }
  245. if (defs->policy_forward == FW3_FLAG_REJECT)
  246. {
  247. r = fw3_ipt_rule_new(handle);
  248. if (!r)
  249. return;
  250. fw3_ipt_rule_target(r, "reject");
  251. fw3_ipt_rule_append(r, "FORWARD");
  252. }
  253. }
  254. static void
  255. set_default(const char *name, int set)
  256. {
  257. FILE *f;
  258. char path[sizeof("/proc/sys/net/ipv4/tcp_window_scaling\0")];
  259. snprintf(path, sizeof(path), "/proc/sys/net/ipv4/tcp_%s", name);
  260. info(" * Set tcp_%s to %s", name, set ? "on" : "off", name);
  261. if (!(f = fopen(path, "w")))
  262. {
  263. info(" ! Unable to write value: %s", strerror(errno));
  264. return;
  265. }
  266. fprintf(f, "%u\n", set);
  267. fclose(f);
  268. }
  269. void
  270. fw3_set_defaults(struct fw3_state *state)
  271. {
  272. set_default("ecn", state->defaults.tcp_ecn);
  273. set_default("syncookies", state->defaults.tcp_syncookies);
  274. set_default("window_scaling", state->defaults.tcp_window_scaling);
  275. }
  276. void
  277. fw3_flush_rules(struct fw3_ipt_handle *handle, struct fw3_state *state,
  278. bool reload)
  279. {
  280. enum fw3_flag policy = reload ? FW3_FLAG_DROP : FW3_FLAG_ACCEPT;
  281. struct fw3_defaults *defs = &state->defaults;
  282. const struct fw3_chain_spec *c;
  283. if (!has(defs->flags, handle->family, handle->table))
  284. return;
  285. if (handle->table == FW3_TABLE_FILTER)
  286. {
  287. fw3_ipt_set_policy(handle, "INPUT", policy);
  288. fw3_ipt_set_policy(handle, "OUTPUT", policy);
  289. fw3_ipt_set_policy(handle, "FORWARD", policy);
  290. }
  291. fw3_ipt_delete_id_rules(handle, "INPUT");
  292. fw3_ipt_delete_id_rules(handle, "OUTPUT");
  293. fw3_ipt_delete_id_rules(handle, "FORWARD");
  294. fw3_ipt_delete_id_rules(handle, "PREROUTING");
  295. fw3_ipt_delete_id_rules(handle, "POSTROUTING");
  296. for (c = default_chains; c->format; c++)
  297. {
  298. /* don't touch user chains on selective stop */
  299. if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS)
  300. continue;
  301. if (!fw3_is_family(c, handle->family))
  302. continue;
  303. if (c->table != handle->table)
  304. continue;
  305. if (c->flag && !has(defs->flags, handle->family, c->flag))
  306. continue;
  307. fw3_ipt_flush_chain(handle, c->format);
  308. /* keep certain basic chains that do not depend on any settings to
  309. avoid purging unrelated user rules pointing to them */
  310. if (reload && !c->flag)
  311. continue;
  312. fw3_ipt_delete_chain(handle, c->format);
  313. }
  314. del(defs->flags, handle->family, handle->table);
  315. }
  316. void
  317. fw3_flush_all(struct fw3_ipt_handle *handle)
  318. {
  319. if (handle->table == FW3_TABLE_FILTER)
  320. {
  321. fw3_ipt_set_policy(handle, "INPUT", FW3_FLAG_ACCEPT);
  322. fw3_ipt_set_policy(handle, "OUTPUT", FW3_FLAG_ACCEPT);
  323. fw3_ipt_set_policy(handle, "FORWARD", FW3_FLAG_ACCEPT);
  324. }
  325. fw3_ipt_flush(handle);
  326. }