{"id":364,"date":"2013-08-02T20:27:18","date_gmt":"2013-08-02T17:27:18","guid":{"rendered":"http:\/\/www.rinta-aho.org\/blog\/?p=364"},"modified":"2015-11-03T10:09:56","modified_gmt":"2015-11-03T08:09:56","slug":"my-openbsd-firewall-pf-single-isp-multiple-dynamic-ips-v3","status":"publish","type":"post","link":"http:\/\/www.rinta-aho.org\/blog\/my-openbsd-firewall-pf-single-isp-multiple-dynamic-ips-v3\/","title":{"rendered":"My OpenBSD firewall: pf + single ISP + multiple dynamic IPs \u2013 v3"},"content":{"rendered":"<p>Upgrading my firewall to OpenBSD 5.3 required updating my &#8220;multihoming-with-single-ISP&#8221; patch (see <a title=\"My OpenBSD firewall: pf + single ISP + multiple dynamic IPs \u2013 v2\" href=\"http:\/\/www.rinta-aho.org\/blog\/?p=346\" target=\"_blank\">previous<\/a> and <a title=\"My OpenBSD firewall: pf + single ISP + multiple dynamic IPs\" href=\"http:\/\/www.rinta-aho.org\/blog\/?p=168\" target=\"_blank\">original<\/a> posts), as <tt>dhclient-script<\/tt> is no longer used. Instead, there is a new file, <tt>kroute.c<\/tt>. Luckily, moving the functionality from the shell script into C code was quite straightforward.<\/p>\n<p>Here is the current patch to <tt>\/usr\/src\/sbin\/dhclient<\/tt>:<\/p>\n<pre>\r\n--- dhclient.c.orig\t2013-08-02 10:17:29.000000000 +0300\r\n+++ dhclient.c\t2013-08-02 10:17:29.000000000 +0300\r\n@@ -858,7 +858,10 @@\r\n \tclient->xid = arc4random();\r\n \tmake_request(client->active);\r\n \r\n-\tif (client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {\r\n+\t\/*if (client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {*\/\r\n+\tif (0 && client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {\r\n \t\tmemcpy(&client->destination.s_addr,\r\n \t\t    client->active->options[DHO_DHCP_SERVER_IDENTIFIER].data,\r\n \t\t    client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len);\r\n--- kroute.c.orig\t2013-08-02 10:17:29.000000000 +0300\r\n+++ kroute.c\t2013-08-02 20:20:42.000000000 +0300\r\n@@ -256,6 +256,9 @@\r\n \tstruct sockaddr_rtlabel label;\r\n \tstruct iovec iov[5];\r\n \tint s, len, i, iovcnt = 0;\r\n+\tchar buf[256];\r\n \r\n \t\/*\r\n \t * Add a default route via the specified address.\r\n@@ -339,6 +342,17 @@\r\n \tiov[iovcnt].iov_base = &label;\r\n \tiov[iovcnt++].iov_len = sizeof(label);\r\n \r\n+\t\/* Update next hop to pf route-to rules *\/\r\n+\tsnprintf(buf, 256, \"\/sbin\/pfctl -t gw_%s -T flush\", ifi->name);\r\n+\tif (system(buf))\r\n+\t\twarning(\"failed to flush pf table: %s\", strerror(errno));\r\n+\tsnprintf(buf, 256, \"\/sbin\/pfctl -t gw_%s -T add %s\", ifi->name,\r\n+\t\tinet_ntoa(gateway.sin_addr));\r\n+\tif (system(buf))\r\n+\t\twarning(\"failed to add to pf table: %s\", strerror(errno));\r\n+\r\n \t\/* Check for EEXIST since other dhclient may not be done. *\/\r\n \tfor (i = 0; i < 5; i++) {\r\n \t\tif (writev(s, iov, iovcnt) != -1)\r\n<\/pre>\n<p>Here is the patch to <tt>\/etc\/rc<\/tt>:<\/p>\n<pre>\r\n--- rc.orig\t2013-08-02 10:17:29.000000000 +0300\r\n+++ rc\t2013-08-02 10:17:29.000000000 +0300\r\n@@ -357,6 +357,14 @@\r\n \tmv -f \/etc\/resolv.conf.save \/etc\/resolv.conf\r\n \ttouch \/etc\/resolv.conf\r\n fi\r\n+\r\n+# Allow em0 to receive vlan packets with different MAC addresses\r\n+ifconfig em0 up\r\n+ifconfig bridge0 create\r\n+brconfig bridge0 add em0\r\n+\r\n . \/etc\/netstart\r\n echo rekey > \/dev\/arandom\t# any write triggers an RC4 rekey\r\n \r\n@@ -370,6 +378,16 @@\r\n \tfi\r\n fi\r\n \r\n+# Initialise next hops for pf's route-to rules\r\n+pfctl -t gw_vlan201 -T add \\\r\n+    `netstat -f inet -rn | grep default | grep vlan201 | awk '{print $2}'`\r\n+pfctl -t gw_vlan202 -T add \\\r\n+    `netstat -f inet -T1 -rn | grep default | grep vlan202 | awk '{print $2}'`\r\n+pfctl -t gw_vlan203 -T add \\\r\n+    `netstat -f inet -T2 -rn | grep default | grep vlan203 | awk '{print $2}'`\r\n+\r\n mount -s \/usr >\/dev\/null 2>&1\r\n mount -s \/var >\/dev\/null 2>&1\r\n<\/pre>\n<p>And finally, this is a working <tt>\/etc\/pf.conf<\/tt>:<\/p>\n<pre>\r\n###############################################################################\r\n# Macros\r\n###############################################################################\r\n\r\nif_int      = \"re0\"\r\nif_ext1     = \"vlan201\"\r\nif_ext2     = \"vlan202\"\r\nif_ext3     = \"vlan203\"\r\nif_extv6    = \"gif0\"\r\nall_ifs     = \"{\" $if_int $if_ext1 $if_ext2 $if_ext3 $if_extv6 \"}\"\r\next_ifs     = \"{\" $if_ext1 $if_ext2 $if_ext3 $if_extv6 \"}\"\r\next_ifs_v4  = \"{\" $if_ext1 $if_ext2 $if_ext3 \"}\"\r\next_ifs_v6  = \"{\" $if_extv6 \"}\"\r\n\r\nif_int_v4   = \"10.0.0.xx\"\r\nhome_net_v4 = \"10.0.0.0\/24\"\r\nif_int_v6ll = \"fe80::xxx\"\r\nif_int_v6   = \"2001:xxx\"\r\nif_ext_v6   = \"2001:xxx\"\r\nhome_net_v6 = \"2001:xxx::\/64\"\r\n\r\ncore7       = \"10.0.0.xx\"\r\nps3         = \"10.0.0.xx\"\r\n\r\n###############################################################################\r\n# Tables\r\n###############################################################################\r\n\r\ntable <gw_vlan201> persist {}\r\ntable <gw_vlan202> persist {}\r\ntable <gw_vlan203> persist {}\r\n\r\ntable <private_nets> const persist {   \\\r\n    127.0.0.0\/8                        \\\r\n    10.0.0.0\/8                         \\\r\n    172.16.0.0\/12                      \\\r\n    192.168.0.0\/16                     \\\r\n}\r\n\r\ntable <ssh_ok> const persist {         \\\r\n    x.x.x.x                            \\\r\n}\r\n\r\ntable <http_ok> const persist {        \\\r\n    x.x.x.x                            \\\r\n}\r\n\r\n###############################################################################\r\n# Options\r\n###############################################################################\r\n\r\nset skip on lo0\r\nset block-policy return\r\nset loginterface $if_ext1\r\nset state-policy if-bound\r\n\r\n###############################################################################\r\n# Packet normalisation\r\n###############################################################################\r\n\r\nmatch on $if_ext1 all scrub (random-id reassemble tcp)\r\nmatch on $if_ext2 all scrub (random-id reassemble tcp)\r\nmatch on $if_ext3 all scrub (random-id)\r\n\r\n## NOTE: \"reassemble tcp\" breaks PS3 downloads and may break something else too\r\n\r\n###############################################################################\r\n# Translation\/redirection rules\r\n###############################################################################\r\n\r\n# FTP proxy states need to override the rules below\r\nanchor \"ftp-proxy\/*\"\r\n\r\n# NAT\r\nmatch out on $if_ext3 inet from $ps3 to any nat-to $if_ext3 static-port\r\nmatch in  on $if_ext3 inet from any to $if_ext3 rdr-to $ps3 rtable 0\r\n\r\nmatch out on $if_ext2 inet from $core7 to any nat-to $if_ext2 static-port\r\nmatch in  on $if_ext2 inet from any to $if_ext2 rdr-to $core7 rtable 0\r\n\r\nmatch out on $if_ext1 from $home_net_v4 nat-to ($if_ext1)\r\n\r\n###############################################################################\r\n# Filter rules\r\n###############################################################################\r\n\r\n##\r\n## GENERAL\r\n##\r\n\r\n# Block and log everything by default\r\nblock log all\r\n\r\n# Antispoofing on all interfaces\r\nantispoof quick for $all_ifs\r\n\r\n# Block private addresses on external interfaces\r\nblock drop in  quick on $ext_ifs from <private_nets>\r\nblock drop out quick on $ext_ifs to   <private_nets>\r\n\r\n# Block IPv6 on external IPv4 interfaces\r\nblock drop quick on $ext_ifs_v4 inet6 all\r\n\r\n# Block IPv4 on external IPv6 interfaces\r\nblock drop quick on $ext_ifs_v6 inet all\r\n\r\n##\r\n## INCOMING\r\n##\r\n\r\n##########\r\n# if_int #\r\n##########\r\n\r\n# FTP proxy\r\npass in quick on $if_int inet proto tcp from $home_net_v4 to port ftp \\\r\n    divert-to 127.0.0.1 port 8021\r\n\r\n# ps3\r\npass in quick on $if_int from $ps3 to $if_int_v4\r\npass in quick on $if_int from $ps3 route-to ($if_ext3 <gw_vlan203>)\r\n\r\n# core7\r\npass in quick on $if_int from $core7 to $if_int_v4\r\npass in quick on $if_int from $core7 route-to ($if_ext2 <gw_vlan202>)\r\n\r\n# Other home network nodes\r\npass in quick on $if_int from $home_net_v4 to $if_int_v4\r\npass in quick on $if_int from $home_net_v4 route-to ($if_ext1 <gw_vlan201>)\r\n\r\n# IPv6\r\npass in quick on $if_int from fe80::\/16 to $if_int_v6ll\r\npass in quick on $if_int from fe80::\/16 to ff02::\/16\r\npass in quick on $if_int from $home_net_v6\r\n\r\n###########\r\n# if_ext1 #\r\n###########\r\n\r\n# IPv6 tunneling\r\npass in quick on $if_ext1 proto icmp from a.b.c.d to ($if_ext1)\r\npass in quick on $if_ext1 proto ipv6 from x.y.z.w to ($if_ext1)\r\n\r\n# Pass in SSH from addresses listed in ssh_ok table\r\npass in quick on $if_ext1 proto tcp from <ssh_ok> to ($if_ext1) port ssh\r\n \r\n# Pass in HTTP from addresses listed in http_ok table\r\npass in quick on $if_ext1 proto tcp from <http_ok> to ($if_ext1) port http\r\n \r\n###################\r\n# if_ext2 (core7) #\r\n###################\r\n\r\n# Steam (https:\/\/support.steampowered.com\/kb_article.php?ref=8571-GLVN-8711)\r\npass in quick on $if_ext2 proto tcp to $core7 port 27014:27050\r\npass in quick on $if_ext2 proto udp to $core7 port 4380\r\npass in quick on $if_ext2 proto udp to $core7 port 27000:27030\r\n\r\n# Black Ops 2\r\npass in quick on $if_ext2 proto tcp to $core7 port 3074\r\npass in quick on $if_ext2 proto udp to $core7 port 3074\r\n\r\n#################\r\n# if_ext3 (ps3) #\r\n#################\r\n\r\n# Nothing\r\n\r\n##\r\n## OUTGOING\r\n##\r\n\r\n##########\r\n# if_int #\r\n##########\r\n\r\n# IPv4 from Internet to home network\r\npass out quick on $if_int to $ps3 received-on $if_ext3 \\\r\n    reply-to ($if_ext3 <gw_vlan203>)\r\npass out quick on $if_int to $core7 received-on $if_ext2 \\\r\n    reply-to ($if_ext2 <gw_vlan202>)\r\npass out quick on $if_int to $home_net_v4 received-on $if_ext1 \\\r\n    reply-to ($if_ext1 <gw_vlan201>)\r\n\r\n# IPv4 from fw to home network\r\npass out quick on $if_int from $if_int_v4 to $home_net_v4\r\n\r\n# IPv6 from fw to home network\r\npass out quick on $if_int from $if_int_v6ll to fe80::\/16\r\npass out quick on $if_int from $if_int_v6ll to ff02::\/16\r\npass out quick on $if_int from $if_int_v6   to $home_net_v6\r\npass out quick on $if_int from $if_int_v6   to ff02::\/16\r\n\r\n###########\r\n# if_ext1 #\r\n###########\r\n\r\n# IPv6 tunneling\r\npass out quick on $if_ext1 proto icmp from ($if_ext1) to a.b.c.d\r\npass out quick on $if_ext1 proto ipv6 from ($if_ext1) to x.y.z.w\r\n\r\n# The rest\r\npass out quick on $if_ext1 inet from ($if_ext1) modulate state\r\n\r\n###################\r\n# if_ext2 (core7) #\r\n###################\r\n\r\npass out quick on $if_ext2 inet from ($if_ext2) modulate state rtable 1\r\n\r\n#################\r\n# if_ext3 (ps3) #\r\n#################\r\n\r\npass out quick on $if_ext3 inet from ($if_ext3) modulate state rtable 2\r\n\r\n############\r\n# if_extv6 #\r\n############\r\n\r\npass out quick on $if_extv6 inet6 from $if_int_v6ll modulate state\r\npass out quick on $if_extv6 inet6 from $if_ext_v6 modulate state\r\npass out quick on $if_extv6 inet6 from $home_net_v6 modulate state\r\n<\/pre>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-32 synved-social-resolution-single synved-social-provider-facebook nolightbox\" data-provider=\"facebook\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Facebook\" href=\"http:\/\/www.facebook.com\/sharer.php?u=http%3A%2F%2Fwww.rinta-aho.org%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F364&#038;t=My%20OpenBSD%20firewall%3A%20pf%20%2B%20single%20ISP%20%2B%20multiple%20dynamic%20IPs%20%E2%80%93%20v3&#038;s=100&#038;p&#091;url&#093;=http%3A%2F%2Fwww.rinta-aho.org%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F364&#038;p&#091;images&#093;&#091;0&#093;=&#038;p&#091;title&#093;=My%20OpenBSD%20firewall%3A%20pf%20%2B%20single%20ISP%20%2B%20multiple%20dynamic%20IPs%20%E2%80%93%20v3\" style=\"font-size: 0px;width:32px;height:32px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"Facebook\" title=\"Share on Facebook\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"32\" height=\"32\" style=\"display: inline;width:32px;height:32px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"http:\/\/www.rinta-aho.org\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/addons\/extra-icons\/image\/social\/clearslate\/64x64\/facebook.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-32 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=http%3A%2F%2Fwww.rinta-aho.org%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F364&#038;text=My%20OpenBSD%20firewall%3A%20pf%20%2B%20single%20ISP%20%2B%20multiple%20dynamic%20IPs%20%E2%80%93%20v3\" style=\"font-size: 0px;width:32px;height:32px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"32\" height=\"32\" style=\"display: inline;width:32px;height:32px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"http:\/\/www.rinta-aho.org\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/addons\/extra-icons\/image\/social\/clearslate\/64x64\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-32 synved-social-resolution-single synved-social-provider-reddit nolightbox\" data-provider=\"reddit\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Reddit\" href=\"https:\/\/www.reddit.com\/submit?url=http%3A%2F%2Fwww.rinta-aho.org%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F364&#038;title=My%20OpenBSD%20firewall%3A%20pf%20%2B%20single%20ISP%20%2B%20multiple%20dynamic%20IPs%20%E2%80%93%20v3\" style=\"font-size: 0px;width:32px;height:32px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"reddit\" title=\"Share on Reddit\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"32\" height=\"32\" style=\"display: inline;width:32px;height:32px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"http:\/\/www.rinta-aho.org\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/addons\/extra-icons\/image\/social\/clearslate\/64x64\/reddit.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-32 synved-social-resolution-single synved-social-provider-pinterest nolightbox\" data-provider=\"pinterest\" target=\"_blank\" rel=\"nofollow\" title=\"Pin it with Pinterest\" href=\"https:\/\/pinterest.com\/pin\/create\/button\/?url=http%3A%2F%2Fwww.rinta-aho.org%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F364&#038;media=&#038;description=My%20OpenBSD%20firewall%3A%20pf%20%2B%20single%20ISP%20%2B%20multiple%20dynamic%20IPs%20%E2%80%93%20v3\" style=\"font-size: 0px;width:32px;height:32px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"pinterest\" title=\"Pin it with Pinterest\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"32\" height=\"32\" style=\"display: inline;width:32px;height:32px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"http:\/\/www.rinta-aho.org\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/addons\/extra-icons\/image\/social\/clearslate\/64x64\/pinterest.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-32 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=http%3A%2F%2Fwww.rinta-aho.org%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F364&#038;title=My%20OpenBSD%20firewall%3A%20pf%20%2B%20single%20ISP%20%2B%20multiple%20dynamic%20IPs%20%E2%80%93%20v3\" style=\"font-size: 0px;width:32px;height:32px;margin:0;margin-bottom:5px;margin-right:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"32\" height=\"32\" style=\"display: inline;width:32px;height:32px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"http:\/\/www.rinta-aho.org\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/addons\/extra-icons\/image\/social\/clearslate\/64x64\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-32 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=My%20OpenBSD%20firewall%3A%20pf%20%2B%20single%20ISP%20%2B%20multiple%20dynamic%20IPs%20%E2%80%93%20v3&#038;body=http%3A%2F%2Fwww.rinta-aho.org%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F364\" style=\"font-size: 0px;width:32px;height:32px;margin:0;margin-bottom:5px\"><img loading=\"lazy\" decoding=\"async\" alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"32\" height=\"32\" style=\"display: inline;width:32px;height:32px;margin: 0;padding: 0;border: none;box-shadow: none\" src=\"http:\/\/www.rinta-aho.org\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/addons\/extra-icons\/image\/social\/clearslate\/64x64\/mail.png\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>Upgrading my firewall to OpenBSD 5.3 required updating my &#8220;multihoming-with-single-ISP&#8221; patch (see previous and original posts), as dhclient-script is no longer used. Instead, there is a new file, kroute.c. Luckily, moving the functionality from the shell script into C code was quite straightforward. Here is the current patch to \/usr\/src\/sbin\/dhclient: &#8212; dhclient.c.orig 2013-08-02 10:17:29.000000000 +0300 &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/www.rinta-aho.org\/blog\/my-openbsd-firewall-pf-single-isp-multiple-dynamic-ips-v3\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;My OpenBSD firewall: pf + single ISP + multiple dynamic IPs \u2013 v3&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-364","post","type-post","status-publish","format-standard","hentry","category-openbsd"],"_links":{"self":[{"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/posts\/364","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/comments?post=364"}],"version-history":[{"count":10,"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/posts\/364\/revisions"}],"predecessor-version":[{"id":374,"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/posts\/364\/revisions\/374"}],"wp:attachment":[{"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/media?parent=364"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/categories?post=364"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.rinta-aho.org\/blog\/wp-json\/wp\/v2\/tags?post=364"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}