{"action":"created","comment":{"url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/comments/48614917","id":48614917,"diff_hunk":"@@ -0,0 +1,95 @@\n+Title: Introducing SnabbWall\n+Date: 2015-12-31 20:00:00\n+Author: aperez\n+Tags: igalia, snabb, snabbwall\n+\n+If you have been following the blogs of my colleagues [Katerina](http://luatime.org), [Diego](http://blogs.igalia.com/dpino/), and [Andy](http://wingolog.org) it should not be a suprise for you to know that in [Igalia](http://www.igalia.com) we have a small —and awesome!— team working with [Snabb Switch](http://snabb.co) to provide novel software–mostly solutions for networking.\n+\n+We are now starting the development of [SnabbWall](http://snabbwall.org) is an *application-level* (Layer-7) firewall *suite* for [Snabb Switch](http://snabb.co), and yours truly happens to be the lead developer, so I figured out this is a good moment to introduce the project, which is kindly sponsored by the [NLnet Foundation](http://nlnet.nl/).\n+\n+\n+<figure style=\"text-align:center\">\n+  ![](http://snabbwall.org/images/igalia-logo.png)\n+  <span style=\"margin-left:20px\">&nbsp;</span>\n+  ![](http://snabbwall.org/images/nlnet-logo.gif)\n+</figure>\n+\n+The one-minute introduction to Snabb\n+------------------------------------\n+\n+Snabb works by taking over network interfaces, bypassing the kernel drivers, and using its own. When used to implement a certain network functinoality, what your (Snabb) program “sees” is no more than streams of raw packets. Gone are the TCP/IP stack, BSD sockets, and all the other functionality provided by the operating system kernel to user space programs. Heck, you even need to roll your [own](https://github.com/SnabbCo/snabbswitch/tree/master/src/apps/intel) [drivers](https://github.com/SnabbCo/snabbswitch/tree/master/src/apps/solarflare)! There is nothing in there but the hardware waiting to have streams of electrons blasted through it. But things go *real* fast in there without the overhead of a traditional network stack, so despite the void it is a good place to massage packets and pass them along.\n+\n+It is fortunate that empty spaces do not last long as such: Snabb comes with a set of [built-in applications](https://github.com/SnabbCo/snabbswitch/tree/master/src/apps), which can be combined in different ways to achieve our (networking-related) goals. For example, we could pick the [bridge application](https://github.com/SnabbCo/snabbswitch/tree/master/src/apps/bridge), combine it with the driver for our network interfaces, and *(bam!)* we have a super fast Ethernet bridge. And even more.\n+\n+Now is when we remember that Snabb is *soft*ware component. That means that it is code running in a computer, as a normal user space program, which can be modified. Why not adding packet filtering capabilities to that bridge we built, so one of the ports only accepts certain kinds of traffic? We could write a small Snabb application which only allows HTTP traffic to pass by:\n+\n+```lua\n+local ethernet = require(\"lib.protocol.ethernet\")\n+local datagram = require(\"lib.protocol.datagram\")\n+local link = require(\"core.link\")\n+\n+local HttpOnly = {\n+  new = function (self) return setmetatable({}, self end;\n+  push = function (self)\n+    local n = math.min(link.nreadable(self.input.input),\n+                       link.nwritable(self.output.output))\n+    for _ = 1, n do\n+      local p = link.receive(self.input.input)\n+      local d = datagram:new(p, ethernet)\n+      d:parse_n(2)\n+      local ip4 = d:stack()[2]\n+      if ip4:sport() == 80 or ip4:dport() == 80 then\n+        link.transmit(self.output.output, p)\n+      end\n+    end\n+  end;\n+}\n+\n+```\n+\n+Well, that was not long. But you can see where this is going: if we are serious about making a full–fledged firewall, our cute little program is going to mutate into something hairy. We would like to have something like [netfilter](http://netfilter.org/) or, even better, something neater which allows to specify rules in a higher level syntax like [OpenBSD's Packet Filter](http://www.openbsd.org/faq/pf/filter.html), package it as a Snabb Switch application, and have it ready for reusing.\n+\n+\n+Dear readers: meet SnabbWall\n+----------------------------\n+\n+SnabbWall is —will be, when completed— a set of Snabb Switch *applications* and *programs*. Applications are reusable in your own designes, like every other Snabb Switch application.\n+\n+<figure class=\"image\">\n+  ![](http://snabbwall.org/images/diagrams/arch-blocks.png)\n+  <figcaption>SnabbWall components</figcaption>\n+</figure>\n+\n+The **L7 Spy** application is capable of identifying protocol data flows (that is, it works in at the [application level](https://en.wikipedia.org/wiki/Application_layer), or Layer-7) but other than that packets just flow through it. The idea here is that sometimes it is interesting to just know which kind of traffic passes through network, for example to gather statistics. If a packet is determined to belong to a certain protocol, ancillary metadata is attached to the packet. The way metadata is handled does not ever modify the packet itself, so applications which are not designed to handle it do not need to be modified.\n+\n+On the other hand, the **L7 Firewall** application implements the actual logic of matching packets against a set of rules which determine what to do with each one of them. What is special about this application is that, on top of what other filtering solutions like [pflua](http://wingolog.org/archives/2014/09/02/high-performance-packet-filtering-with-pflua) may offer, it also allows to match the additional metadata generated by L7 Spy — if present.\n+\n+Note that it is not at all necessary to use both applications in tandem: they can function independently, to allow others to mix-and-match them as desired. Yet, they are designed to work together, and SnabbWall also provides a standalone program (`snabb wall`) which implements a complete application-level firewall.\n+\n+\n+Deep Space 9\n+------------\n+\n+Inferring the protocol to which a packet belongs is a tough job: it requires inspecting the whole contents of each packet, including decoding of protocol fields and reading the data payloads. This is typically referred to as [deep packet inspection](https://en.wikipedia.org/wiki/Deep_packet_inspection) (DPI), and if the term makes you feel uneasy it is not without reason: DPI is used by evil governments and faceless corporations to eavesdrop on us *netizens*, or by greedy Internet service providers to cap some kinds of traffic thus attacking net neutrality. Which does not mean that DPI is bad *per se*: like any other tool, it can be used also to pursue noble purposes. Who wouldn't want their video calls to be smooth thanks to the network giving priority to real time audio and video after all? DPI is just one more tool, and as such it can be misused — [so can a hammer](https://www.priv.gc.ca/information/research-recherche/2009/lewis_200905_e.asp). But implementing DPI algorithms is not among the goals of the project — if possible. A hammer had to be chosen.\n+\n+There are Free Software solutions which already provide DPI functionality. After evaluating the candidates, it was decided that SnabbWall (in particular, the L7 Spy application) would use [nDPI](http://www.ntop.org/products/ndpi/). It is a well-maintained, reliable piece of software, with a C API which lends itself to be wrapped using [LuaJIT's FFI](http://luajit.org/ext_ffi_api.html). It has a long story —for a piece of software— as it started life as OpenDPI, which itself was a trimmed down version of a commercial product, and along its multiple lifes it has been tweaked to the point that nDPI provides the best protocol/application detection of the pack.","path":"2015/introducing-snabbwall.markdown","position":75,"original_position":75,"commit_id":"620b0f63d8faa7eaf9186b3e568de37c8dcbe6d9","original_commit_id":"620b0f63d8faa7eaf9186b3e568de37c8dcbe6d9","user":{"login":"dpino","id":11567,"avatar_url":"https://avatars.githubusercontent.com/u/11567?v=3","gravatar_id":"","url":"https://api.github.com/users/dpino","html_url":"https://github.com/dpino","followers_url":"https://api.github.com/users/dpino/followers","following_url":"https://api.github.com/users/dpino/following{/other_user}","gists_url":"https://api.github.com/users/dpino/gists{/gist_id}","starred_url":"https://api.github.com/users/dpino/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dpino/subscriptions","organizations_url":"https://api.github.com/users/dpino/orgs","repos_url":"https://api.github.com/users/dpino/repos","events_url":"https://api.github.com/users/dpino/events{/privacy}","received_events_url":"https://api.github.com/users/dpino/received_events","type":"User","site_admin":false},"body":"Typo: s/lifes/lives/","created_at":"2015-12-30T16:43:04Z","updated_at":"2015-12-30T16:43:04Z","html_url":"https://github.com/aperezdc/perezdecastro.org/pull/1#discussion_r48614917","pull_request_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/comments/48614917"},"html":{"href":"https://github.com/aperezdc/perezdecastro.org/pull/1#discussion_r48614917"},"pull_request":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1","id":54805727,"html_url":"https://github.com/aperezdc/perezdecastro.org/pull/1","diff_url":"https://github.com/aperezdc/perezdecastro.org/pull/1.diff","patch_url":"https://github.com/aperezdc/perezdecastro.org/pull/1.patch","issue_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/1","number":1,"state":"open","locked":false,"title":"SnabbWall introduction article","user":{"login":"aperezdc","id":723451,"avatar_url":"https://avatars.githubusercontent.com/u/723451?v=3","gravatar_id":"","url":"https://api.github.com/users/aperezdc","html_url":"https://github.com/aperezdc","followers_url":"https://api.github.com/users/aperezdc/followers","following_url":"https://api.github.com/users/aperezdc/following{/other_user}","gists_url":"https://api.github.com/users/aperezdc/gists{/gist_id}","starred_url":"https://api.github.com/users/aperezdc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aperezdc/subscriptions","organizations_url":"https://api.github.com/users/aperezdc/orgs","repos_url":"https://api.github.com/users/aperezdc/repos","events_url":"https://api.github.com/users/aperezdc/events{/privacy}","received_events_url":"https://api.github.com/users/aperezdc/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-12-30T15:08:01Z","updated_at":"2015-12-30T16:43:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7fb808412f8f51789617dc5cac0770d6b563a3f7","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1/commits","review_comments_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1/comments","review_comment_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/comments{/number}","comments_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/1/comments","statuses_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/statuses/620b0f63d8faa7eaf9186b3e568de37c8dcbe6d9","head":{"label":"aperezdc:snabbwall-intro","ref":"snabbwall-intro","sha":"620b0f63d8faa7eaf9186b3e568de37c8dcbe6d9","user":{"login":"aperezdc","id":723451,"avatar_url":"https://avatars.githubusercontent.com/u/723451?v=3","gravatar_id":"","url":"https://api.github.com/users/aperezdc","html_url":"https://github.com/aperezdc","followers_url":"https://api.github.com/users/aperezdc/followers","following_url":"https://api.github.com/users/aperezdc/following{/other_user}","gists_url":"https://api.github.com/users/aperezdc/gists{/gist_id}","starred_url":"https://api.github.com/users/aperezdc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aperezdc/subscriptions","organizations_url":"https://api.github.com/users/aperezdc/orgs","repos_url":"https://api.github.com/users/aperezdc/repos","events_url":"https://api.github.com/users/aperezdc/events{/privacy}","received_events_url":"https://api.github.com/users/aperezdc/received_events","type":"User","site_admin":false},"repo":{"id":10707424,"name":"perezdecastro.org","full_name":"aperezdc/perezdecastro.org","owner":{"login":"aperezdc","id":723451,"avatar_url":"https://avatars.githubusercontent.com/u/723451?v=3","gravatar_id":"","url":"https://api.github.com/users/aperezdc","html_url":"https://github.com/aperezdc","followers_url":"https://api.github.com/users/aperezdc/followers","following_url":"https://api.github.com/users/aperezdc/following{/other_user}","gists_url":"https://api.github.com/users/aperezdc/gists{/gist_id}","starred_url":"https://api.github.com/users/aperezdc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aperezdc/subscriptions","organizations_url":"https://api.github.com/users/aperezdc/orgs","repos_url":"https://api.github.com/users/aperezdc/repos","events_url":"https://api.github.com/users/aperezdc/events{/privacy}","received_events_url":"https://api.github.com/users/aperezdc/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/aperezdc/perezdecastro.org","description":"Personal website and static site generator in NodeJS","fork":false,"url":"https://api.github.com/repos/aperezdc/perezdecastro.org","forks_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/forks","keys_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/teams","hooks_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/hooks","issue_events_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/events{/number}","events_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/events","assignees_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/assignees{/user}","branches_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/branches{/branch}","tags_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/tags","blobs_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/refs{/sha}","trees_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/statuses/{sha}","languages_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/languages","stargazers_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/stargazers","contributors_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/contributors","subscribers_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/subscribers","subscription_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/subscription","commits_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/commits{/sha}","git_commits_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/commits{/sha}","comments_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/comments{/number}","issue_comment_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/comments{/number}","contents_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/contents/{+path}","compare_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/merges","archive_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/downloads","issues_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues{/number}","pulls_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls{/number}","milestones_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/milestones{/number}","notifications_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/labels{/name}","releases_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/releases{/id}","created_at":"2013-06-15T14:40:32Z","updated_at":"2015-06-24T20:03:38Z","pushed_at":"2015-12-30T15:08:03Z","git_url":"git://github.com/aperezdc/perezdecastro.org.git","ssh_url":"git@github.com:aperezdc/perezdecastro.org.git","clone_url":"https://github.com/aperezdc/perezdecastro.org.git","svn_url":"https://github.com/aperezdc/perezdecastro.org","homepage":null,"size":2260,"stargazers_count":1,"watchers_count":1,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":1,"default_branch":"master"}},"base":{"label":"aperezdc:master","ref":"master","sha":"b5ce1e29ff91a7d0b32830df934f0f5a7872b7cb","user":{"login":"aperezdc","id":723451,"avatar_url":"https://avatars.githubusercontent.com/u/723451?v=3","gravatar_id":"","url":"https://api.github.com/users/aperezdc","html_url":"https://github.com/aperezdc","followers_url":"https://api.github.com/users/aperezdc/followers","following_url":"https://api.github.com/users/aperezdc/following{/other_user}","gists_url":"https://api.github.com/users/aperezdc/gists{/gist_id}","starred_url":"https://api.github.com/users/aperezdc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aperezdc/subscriptions","organizations_url":"https://api.github.com/users/aperezdc/orgs","repos_url":"https://api.github.com/users/aperezdc/repos","events_url":"https://api.github.com/users/aperezdc/events{/privacy}","received_events_url":"https://api.github.com/users/aperezdc/received_events","type":"User","site_admin":false},"repo":{"id":10707424,"name":"perezdecastro.org","full_name":"aperezdc/perezdecastro.org","owner":{"login":"aperezdc","id":723451,"avatar_url":"https://avatars.githubusercontent.com/u/723451?v=3","gravatar_id":"","url":"https://api.github.com/users/aperezdc","html_url":"https://github.com/aperezdc","followers_url":"https://api.github.com/users/aperezdc/followers","following_url":"https://api.github.com/users/aperezdc/following{/other_user}","gists_url":"https://api.github.com/users/aperezdc/gists{/gist_id}","starred_url":"https://api.github.com/users/aperezdc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aperezdc/subscriptions","organizations_url":"https://api.github.com/users/aperezdc/orgs","repos_url":"https://api.github.com/users/aperezdc/repos","events_url":"https://api.github.com/users/aperezdc/events{/privacy}","received_events_url":"https://api.github.com/users/aperezdc/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/aperezdc/perezdecastro.org","description":"Personal website and static site generator in NodeJS","fork":false,"url":"https://api.github.com/repos/aperezdc/perezdecastro.org","forks_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/forks","keys_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/teams","hooks_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/hooks","issue_events_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/events{/number}","events_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/events","assignees_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/assignees{/user}","branches_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/branches{/branch}","tags_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/tags","blobs_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/refs{/sha}","trees_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/statuses/{sha}","languages_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/languages","stargazers_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/stargazers","contributors_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/contributors","subscribers_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/subscribers","subscription_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/subscription","commits_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/commits{/sha}","git_commits_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/git/commits{/sha}","comments_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/comments{/number}","issue_comment_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/comments{/number}","contents_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/contents/{+path}","compare_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/merges","archive_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/downloads","issues_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues{/number}","pulls_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls{/number}","milestones_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/milestones{/number}","notifications_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/labels{/name}","releases_url":"https://api.github.com/repos/aperezdc/perezdecastro.org/releases{/id}","created_at":"2013-06-15T14:40:32Z","updated_at":"2015-06-24T20:03:38Z","pushed_at":"2015-12-30T15:08:03Z","git_url":"git://github.com/aperezdc/perezdecastro.org.git","ssh_url":"git@github.com:aperezdc/perezdecastro.org.git","clone_url":"https://github.com/aperezdc/perezdecastro.org.git","svn_url":"https://github.com/aperezdc/perezdecastro.org","homepage":null,"size":2260,"stargazers_count":1,"watchers_count":1,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":1,"forks":2,"open_issues":1,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1"},"html":{"href":"https://github.com/aperezdc/perezdecastro.org/pull/1"},"issue":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/1"},"comments":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/aperezdc/perezdecastro.org/statuses/620b0f63d8faa7eaf9186b3e568de37c8dcbe6d9"}}}}