Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ript: making Linux firewall change management resilient

Ript: making Linux firewall change management resilient

Netfilter is an extremely powerful framework for manipulating packets, but does anyone enjoy using iptables? Tools for managing small rulesets have a steep learning curve, and most tools don't take availablity into account when managing large rulesets.

Enter Ript, a clean and opinionated Domain Specific Language for describing firewall rules, and a tool that implements database migrations-like functionality for applying these rules with zero downtime.

At Ript's core is an easy to use Ruby DSL for describing both simple and complex sets of iptables firewall rules, with helpers for all the common use cases: accepting, dropping, & rejecting packets, as well as for performing DNAT and SNAT.

Ript provides a method to group common sets of rules together called "partitions", which are used at rule application time to perform zero-downtime migrations.

In this talk Lindsay Holmwood takes you on a whirlwind tour of the DSL, explaining how Ript utilises iptables features to work its magic, and providing some concrete examples of how Ript can help increase the reliability of the services you deliver.

Fad1e9ed293fc5b3ec7d4abdffeb636f?s=128

Lindsay Holmwood

January 30, 2013
Tweet

Transcript

  1. Ript making Linux firewall change management resilient

  2. Hi!

  3. I am Lindsay Holmwood @auxesis

  4. None
  5. 2008

  6. None
  7. @auxesis

  8. @imprecise_matt

  9. An interesting problem

  10. Scenario:

  11. BULLETPROOF

  12. IaaS & Managed Hosting

  13. Multi-tenant firewalls

  14. Many rules per-tenant

  15. Existing tool to describe rules

  16. But builds rules in a dumb way

  17. Rules application == downtime

  18. Worse: Changes for one tenant affect others

  19. Rules application == downtime

  20. Rules application == downtime (for all tenants)

  21. None
  22. Rule application 0(n)

  23. Lack of expressiveness when describing rules

  24. Brittle, error prone framework for describing rules

  25. Looking for tool:

  26. Compartmentalises changes

  27. Zero downtime changes

  28. Friendly language for describing rules

  29. Shortcuts to DRY up rules

  30. None
  31. Hacked in the car

  32. Rough prototype

  33. No iptables rule generation

  34. Focus on the language

  35. What would the DSL look like?

  36. What do the resulting data structures look like?

  37. Ruby + IPTables

  38. Questions answered. Thought experiment: complete

  39. None
  40. 2010: hired at Bulletproof

  41. Outage Discussion

  42. Seed planted

  43. Bigger fish to fry

  44. None
  45. Resumed in March 2011

  46. commit b1625ead6c7fcb814a39f1db5a2d43acfbab80a1 Author: Lindsay Holmwood <lindsay@holmwood.id.au> Date: Thu Mar 24

    14:45:29 2011 +1100 initial commit
  47. Thursday arvo skunkworks project

  48. Steve Fisher: org knowledge change mgmt experience Lindsay Holmwood: iptables

    knowledge testing experience
  49. Prototyped the DSL

  50. partition "movember" do interface :default => "vlan666" address :iemedia, :address

    => "192.168.55.70/27", :interface => "vlan99" address "www.movember.com", :address => "117.53.174.95", :interface => "vlan44" address "movember subnet", :address => "117.53.174.0/27", :interface => "vlan44" address "mo2010prod-dvmh-web-01", :address => "10.0.21.2" address "mo2010prod-dvmh-proxy-01", :address => "10.0.21.3" address "mo2010prod-dvmh-app-01", :address => "10.0.21.4" address "mo2010prod subnet", :address => "10.0.21.0/27" address "mo2010prod-dvmh-ipv-06", :address => "00:00:de:ca:fe:c0:ff:33" address "dickhead", :address => "127.0.0.1" # ...
  51. # ... reject "dickhead on www.movember.com" do from "dickhead" to

    "www.movember.com" end log "dickhead on www.movember.com" do from "dickhead" to "www.movember.com" end # dnat forward "movember.com public website" do ports 80, 443 dnat "www.movember.com" => "mo2010prod-dvmh-web-01" end # snat forward "movember" do to :anywhere snat "mo2010prod subnet" => "www.movember.com" end # nonat forward "ipv6 forward" do ports 80, 443 from :anywhere nonat "mo2010prod-dvmh-ipv-06" end end
  52. Tested the DSL

  53. Outside-in

  54. Implemented migrations

  55. Zero downtime changes

  56. Compartmentalises changes

  57. Took it live

  58. Now in use by: Whirlpool, One Big Switch, Tourism Victoria,

    Network TEN, Movember, Quicksilver, IMAX, Bookworld, ABC, SBS
  59. None
  60. None
  61. The Language

  62. Partitions

  63. partition "joeblogsco" do # ... end

  64. partition "joeblogsco" do # Labels + rules go here end

  65. Labels

  66. partition "joeblogsco" do end

  67. partition "joeblogsco" do end partition "joeblogsco" do label "www.joeblogsco.com", :address

    => "172.19.56.216" label "api.joeblogsco.com", :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" end
  68. partition "joeblogsco" do end partition "joeblogsco" do label "www.joeblogsco.com", :address

    => "172.19.56.216" label "api.joeblogsco.com", :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" end key
  69. partition "joeblogsco" do end partition "joeblogsco" do label "www.joeblogsco.com", :address

    => "172.19.56.216" label "api.joeblogsco.com", :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" end key data
  70. Scoped to a partition

  71. # joeblogsco.rb partition "joeblogsco" do label "app-01", :address => "192.168.5.230"

    end # foobar.rb partition "foobar" do label "app-01", :address => "192.168.78.3" end
  72. # joeblogsco.rb partition "joeblogsco" do label "app-01", :address => "192.168.5.230"

    end # foobar.rb partition "foobar" do label "app-01", :address => "192.168.78.3" end no conflicts
  73. Rules

  74. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" end
  75. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end end
  76. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end end comment
  77. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end end comment arguments
  78. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end rewrite "public ssh access" do ports 22 dnat "www.joeblogsco.com" => "app-01" end end
  79. Default policy: DROP

  80. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end end
  81. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end end need an accept
  82. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end end
  83. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end accept "allow public ssh access" do protocols "tcp" ports 22 to "www.joeblogsco.com" end end
  84. Ript does this for you!

  85. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end end
  86. equals

  87. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end accept "allow public ssh access" do protocols "tcp" ports 22 to "www.joeblogsco.com" end end
  88. DRY

  89. Cleanup

  90. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end rewrite "public ssh access" do ports 22 dnat "www.joeblogsco.com" => "app-01" end end
  91. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website + ssh access" do ports 80, 22 dnat "www.joeblogsco.com" => "app-01" end end
  92. Lockdown

  93. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end rewrite "trusted ssh access" do ports 22 dnat "www.joeblogsco.com" => "app-01" end end
  94. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "api.joeblogsco.com",

    :address => "172.19.56.217" label "joeblogsco subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" label "trusted office", :address => "172.20.4.124" rewrite "public website" do ports 80 dnat "www.joeblogsco.com" => "app-01" end rewrite "trusted ssh access" do ports 22 from "trusted office" dnat "www.joeblogsco.com" => "app-01" end end
  95. Ports

  96. None
  97. rewrite "public mail" do ports 25, 993 dnat "www.joeblogsco.com" =>

    "app-01" end
  98. rewrite "public mail" do ports 25, 993 dnat "www.joeblogsco.com" =>

    "app-01" end rewrite "trusted private services" do from "trusted office" ports 6000..8000 dnat "www.joeblogsco.com" => "app-01" end
  99. rewrite "public mail" do ports 25, 993 dnat "www.joeblogsco.com" =>

    "app-01" end rewrite "trusted private services" do from "trusted office" ports 6000..8000 dnat "www.joeblogsco.com" => "app-01" end rewrite "public website" do ports 80 => 8080 dnat "www.joeblogsco.com" => "app-01" end
  100. rewrite "public mail" do ports 25, 993 dnat "www.joeblogsco.com" =>

    "app-01" end rewrite "trusted private services" do from "trusted office" ports 6000..8000 dnat "www.joeblogsco.com" => "app-01" end rewrite "public website" do ports 80 => 8080 dnat "www.joeblogsco.com" => "app-01" end rewrite "api services" do ports 80, 8000..8900, 2222 => 22 dnat "api.joeblogsco.com" => "app-02" end
  101. rewrite "public mail" do ports 25, 993 dnat "www.joeblogsco.com" =>

    "app-01" end rewrite "trusted private services" do from "trusted office" ports 6000..8000 dnat "www.joeblogsco.com" => "app-01" end rewrite "public website" do ports 80 => 8080 dnat "www.joeblogsco.com" => "app-01" end rewrite "api services" do ports 80, 8000..8900, 2222 => 22 dnat "api.joeblogsco.com" => "app-02" end mappings must be last
  102. Protocols

  103. rewrite "public mail" do ports 25, 993 dnat "www.joeblogsco.com" =>

    "app-01" end
  104. rewrite "public mail" do protocols "tcp" ports 25, 993 dnat

    "www.joeblogsco.com" => "app-01" end
  105. More rules

  106. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "joeblogsco

    subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" rewrite "private to public" do snat "joeblogsco subnet" => "www.joeblogsco.com" end end
  107. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "joeblogsco

    subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" label "bad guy", :address => "172.19.110.247" rewrite "public website + ssh access" do ports 80, 22 dnat "www.joeblogsco.com" => "app-01" end drop "bad guy" do from "bad guy" to "www.joeblogsco.com" end end
  108. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "joeblogsco

    subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" label "bad guys", :address => "172.19.110.0/8" rewrite "public website + ssh access" do ports 80, 22 dnat "www.joeblogsco.com" => "app-01" end drop "bad guys" do protocols "udp" from "bad guys" to "www.joeblogsco.com" end end
  109. partition "joeblogsco" do label "www.joeblogsco.com", :address => "172.19.56.216" label "joeblogsco

    subnet", :address => "192.168.5.224/27" label "app-01", :address => "192.168.5.230" label "bad guys", :address => "172.19.110.0/8" rewrite "public website + ssh access", :log => true do ports 80, 22 dnat "www.joeblogsco.com" => "app-01" end drop "bad guys", :log => true do protocols "udp" from "bad guys" to "www.joeblogsco.com" end end
  110. Shortcuts

  111. partition "joeblogsco" do label "joeblogsco uat subnet", :address => "192.168.5.0/24"

    label "joeblogsco stage subnet", :address => "10.60.2.0/24" label "joeblogsco prod subnet", :address => "10.60.3.0/24" label "www.joeblogsco.com", :address => "172.19.56.216" rewrite "private to public" do snat [ "joeblogsco uat subnet", "joeblogsco stage subnet", "joeblogsco prod subnet" ] => "www.joeblogsco.com" end end
  112. accept "fruits of the forest" do protocols "tcp" ports 22

    from %w(apple blueberry cranberry eggplant fennel grapefruit) to %w(apple blueberry cranberry eggplant fennel grapefruit) end
  113. None
  114. The Rationale

  115. Existing tool to describe rules

  116. But builds rules in a dumb way

  117. Rules application == downtime (for all tenants)

  118. Large changes

  119. Poor separation of concern

  120. None
  121. How to fix?

  122. Increase frequency

  123. Limit size

  124. Remove friction

  125. Continuous delivery

  126. change windows

  127. My change windows are 24/7

  128. Reduce risk

  129. Release early, Release often

  130. Fail fast, Recover quickly

  131. None
  132. How do other people solve this problem?

  133. Incrementalism

  134. What about the current state?

  135. Current (unknown) state Desired state

  136. Inspiration: Active Record Migrations

  137. Migrations can manage the evolution of a schema used by

    several physical databases. It’s a solution to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to push that change to other developers and to the production server. With migrations, you can describe the transformations in self-contained classes that can be checked into version control systems and execute against another database that might be one, two, or five versions behind. -- http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
  138. Migrations can manage the evolution of a schema used by

    several physical databases. It’s a solution to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to push that change to other developers and to the production server. With migrations, you can describe the transformations in self-contained classes that can be checked into version control systems and execute against another database that might be one, two, or five versions behind. -- http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
  139. class AddSsl < ActiveRecord::Migration def up add_column :accounts, :ssl_enabled, :boolean

    end def down remove_column :accounts, :ssl_enabled end end
  140. Sequel.migration do up do create_table(:artists) do primary_key :id String :name,

    :null => false end end down do drop_table(:artists) end end
  141. Sequel.migration do change do create_table(:artists) do primary_key :id String :name,

    :null => false end end end
  142. ➔ ls -1 db/migrations/ | head -n 20 001_initialize.rb 002_add_test_column.rb

    003_2012Iteration2.rb 004_2012Iteration3.rb 005_2012Iteration4.rb 006_2012Iteration5.rb 007_2012Iteration6.rb 008_2012Iteration7.rb 009_2012Iteration8.rb 010_2012Iteration8.rb 011_2012Gateways.rb 012_2012Iteration8FAQ.rb 013_2012NetworkUpdates.rb 014_2012DonationDenmark.rb
  143. ➔ sequel -m db/migrations postgres://localhost/database

  144. None
  145. Show me!

  146. None
  147. So... how does it work?

  148. iptables

  149. INPUT FORWARD OUTPUT Packets originating locally Packets to be delivered

    locally Packets being forwarded FILTER table
  150. NAT table PREROUTING POSTROUTING Packets for DNAT Packets for SNAT

  151. None
  152. Ript-specific chains

  153. before-a

  154. Traffic scrubbing (ICMP, stateful inspection, keepalive CONNMARK) before-a

  155. Boilerplate chain You will never touch this before-a

  156. Pointers to partition access chains INPUT + OUTPUT + FORWARD

    all jump to partition-a partition-a
  157. Rules for the partition named moprodau moprodau-a123abc

  158. moprodau-a123abc

  159. moprodau-a123abc

  160. moprodau-a123abc partition name

  161. moprodau-a123abc partition name ruleset type a - access, d -

    dnat, s - snat
  162. moprodau-a123abc partition name ruleset type a - access, d -

    dnat, s - snat ruleset hash
  163. None
  164. Chain traversal

  165. None
  166. FORWARD OUTPUT INPUT

  167. FORWARD OUTPUT INPUT

  168. FORWARD OUTPUT INPUT before-a

  169. FORWARD OUTPUT INPUT before-a

  170. FORWARD OUTPUT INPUT before-a FORWARD OUTPUT INPUT

  171. FORWARD OUTPUT INPUT before-a FORWARD OUTPUT INPUT

  172. partition-a FORWARD OUTPUT INPUT before-a FORWARD OUTPUT INPUT

  173. partition-a

  174. partition-a

  175. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce partition-a

  176. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce partition-a

  177. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce partition-a

  178. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce partition-a

  179. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce partition-a

  180. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce partition-a

  181. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce partition-a

  182. rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce FORWARD OUTPUT INPUT partition-a

  183. None
  184. jump to partition _ pointers chains

  185. There are for each destination pointers

  186. match on source + destination pointers

  187. Makes traversal of quick partition-a

  188. None
  189. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  190. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  191. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  192. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  193. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  194. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  195. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  196. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  197. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  198. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  199. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  200. d c e abcradio-a3e32ce

  201. d e ec ce abcradio-a3e32ce

  202. d e ec ce abcradio-a3e32ce Verdict

  203. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  204. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  205. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  206. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  207. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  208. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  209. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  210. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Verdict
  211. d e ec ce abcradio-a3e32ce

  212. d e ec ce abcradio-a3e32ce Logging

  213. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Logging
  214. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Logging
  215. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Logging
  216. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Logging
  217. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Logging
  218. d e ec ce abcradio-a3e32ce log 117.53.167.72 accept 117.53.167.72 reject

    117.53.173.17 accept 117.53.180.9 Logging
  219. None
  220. Zero downtime migrations

  221. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce

  222. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce # ript rules apply

  223. partition-a rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce # ript rules apply

  224. partition-a bwired-a67edce rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec abcradio-a3e32ce # ript rules apply

  225. partition-a bwired-a67edce rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec # ript rules apply

  226. partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec # ript rules apply

  227. None
  228. ript rules apply always inserts at the top of _

    partition-a pointers
  229. None
  230. # ript rules apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec

  231. overlapping pointers # ript rules apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d

    bwired-ac12dce moprodau-a9c4dec
  232. overlapping pointers # ript rules apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d

    bwired-ac12dce moprodau-a9c4dec
  233. # ript rules apply overlapping pointers partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d

    bwired-ac12dce moprodau-a9c4dec
  234. None
  235. None
  236. bwired-a67edce

  237. bwired-a67edce accept 117.53.168.72:80 ...

  238. bwired-a67edce accept 117.53.168.72:80 ...

  239. bwired-a67edce accept 117.53.168.72:80 ...

  240. bwired-a67edce accept 117.53.168.72:80 ... no match, returns to partition-a

  241. bwired-a67edce accept 117.53.168.72:80 ... bwired-ac12dce no match, returns to partition-a

  242. bwired-a67edce accept 117.53.168.72:80 ... bwired-ac12dce no match, returns to partition-a

    same destination, jumps into old chain
  243. bwired-a67edce accept 117.53.168.72:80 ... bwired-ac12dce accept 117.53.167.72:22 ... no match,

    returns to partition-a same destination, jumps into old chain
  244. bwired-a67edce accept 117.53.168.72:80 ... bwired-ac12dce accept 117.53.167.72:22 ... no match,

    returns to partition-a same destination, jumps into old chain
  245. bwired-a67edce accept 117.53.168.72:80 ... bwired-ac12dce accept 117.53.167.72:22 ... no match,

    returns to partition-a same destination, jumps into old chain hits old rule
  246. You need to clean the rules!

  247. None
  248. ript clean apply

  249. # ript clean apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec

  250. identical partition name # ript clean apply partition-a abcradio-a023fe8 bwired-a67edce

    rgrprod-a5af73d bwired-ac12dce moprodau-a9c4dec
  251. # ript clean apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d moprodau-a9c4dec

  252. # ript clean apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d moprodau-a9c4dec abcradio-a3e32ce

  253. # ript clean apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d abcradio-a3e32ce moprodau-a9c4dec

  254. identical partition name # ript clean apply partition-a abcradio-a023fe8 bwired-a67edce

    rgrprod-a5af73d abcradio-a3e32ce moprodau-a9c4dec
  255. # ript clean apply partition-a abcradio-a023fe8 bwired-a67edce rgrprod-a5af73d moprodau-a9c4dec

  256. None
  257. Workflows

  258. git

  259. Config mgmt

  260. None
  261. Real world example

  262. What workflow does Bulletproof use?

  263. Install Ript with Puppet

  264. ript.rules repo

  265. Deploy with Capistrano

  266. /etc/firewall/current

  267. cap deploy

  268. ript rules diff

  269. cap deploy apply=true

  270. ript rules apply

  271. None
  272. Vagrant

  273. None
  274. Challenges

  275. Testing

  276. Cucumber

  277. Outside-in

  278. Lots of examples Used by tests

  279. ~/code/ript ➔ ls -1 examples/ |wc -l 41

  280. Systems code

  281. Lingering state

  282. rake clean_slate

  283. None
  284. Open Sourcing

  285. We love Open Source!

  286. *but*

  287. Minimum Viable Product

  288. Started concrete

  289. Hard coded Bulletproofisms

  290. Scrub internal references

  291. Rewrite history

  292. None
  293. Nuke git repo

  294. ~/code/ript.history ➔ git log --pretty=format:%H |wc -l 234 ~/code/ript.public ➔

    git log --pretty=format:%H |wc -l 5
  295. Retained CHANGELOG

  296. None
  297. Interface

  298. bin/ript

  299. A little manky

  300. On the roadmap

  301. None
  302. IPv6

  303. No current support

  304. Really important

  305. .to_iptables

  306. .to_ip6tables

  307. Q2 2013

  308. None
  309. Writing our own history

  310. Too easy to complain

  311. Question your circumstances.

  312. Working with shitty tools?

  313. What lead you to this point?

  314. What is the problem you're trying to solve?

  315. Tools are a means

  316. They can be rebuilt, rewritten, replaced

  317. Find your concrete principals

  318. Frequency

  319. Size

  320. Friction

  321. Thank you! Questions?

  322. Questions? Tweet @auxesis if you liked the talk!

  323. None
  324. http://www.flickr.com/photos/25084516@N03/4994100153 http://www.flickr.com/photos/pfenwick/2237728495 http://www.flickr.com/photos/varrqnuht/2228404970 http://www.flickr.com/photos/t3rmin4t0r/2276495257 http://www.flickr.com/photos/chrissamuel/2231908105 http://www.flickr.com/photos/nhankamer/4703022414 http://www.flickr.com/photos/nortonp/6236722793 http://www.flickr.com/photos/thomasforsyth/4313764488 http://www.flickr.com/photos/mag3737/204597831 http://www.flickr.com/photos/carleycomartin/3912655528

    http://www.flickr.com/photos/thomas_hackl/8172975389 http://www.flickr.com/photos/memestate/54408373 http://www.flickr.com/photos/ldsykora/2414497811 http://www.flickr.com/photos/usdagov/7061668841 http://www.flickr.com/photos/studiogabe/5213143779 http://www.flickr.com/photos/terrio/4303997455 http://www.flickr.com/photos/cmbellman/3219012282 Credits
  325. http://www.flickr.com/photos/sizemore/2215594186 http://www.flickr.com/photos/tsuna72/5939008153 http://www.flickr.com/photos/stevensnodgrass/3543579066 http://www.flickr.com/photos/altemark/363947977 http://www.flickr.com/photos/moff/4504997898 http://www.flickr.com/photos/charlestilford/8295523130 http://www.flickr.com/photos/nasacommons/4858567480 http://www.vagrantup.com/images/vagrant_header_background-482a12a7.png http://www.flickr.com/photos/10318341@N02/4425899887 http://www.flickr.com/photos/deadair/3361335831

    http://www.flickr.com/photos/zanehollingsworth/3260908168 http://www.flickr.com/photos/cushinglibrary/3740398710 http://www.flickr.com/photos/89964047@N07/8181225923 http://www.flickr.com/photos/minnesotahistoricalsociety/5186865305 http://www.flickr.com/photos/58558794@N07/5739801904 http://www.flickr.com/photos/steverhode/3134180338 http://www.flickr.com/photos/acediscovery/3030548744 Credits