Jekyll2019-07-18T16:07:22+00:00http://gsoc-blog.ecklm.com/feed.xmlWhat I’ve learned during GSoCHere I describe what I've learned during contributing to the netfilter project during my GSoC participation in 2018 hoping that it will help others looking for hard-to find information.GSoC 2018 project submission2018-08-08T00:00:00+00:002018-08-08T00:00:00+00:00http://gsoc-blog.ecklm.com/gsoc-2018-project-submission<p>Here I’d like to summarise my efforts until the publishing day of this post in
the netfilter project as part of the Google Summer of Code 2018 program. This
will also serve as a product submission which Google requires as a final part of
the program.</p>
<p>I proposed to implement native transparent proxy support in <code class="highlighter-rouge">nf_tables</code> on both
user- and kernel levels (see my proposal
<a href="http://gsoc-blog.ecklm.com/gsoc-2018-proposal/">here</a>). This functionality had
already been part of <code class="highlighter-rouge">x_tables</code> so a part of my job was to refactor the
existing code so that core functions can be used from the new module.</p>
<p>Documentation can be found in the nft(8) man page after applying my patches.</p>
<h2 id="socket-match-implementation">Socket match implementation</h2>
<p>Half of the job was to implement socket matching which can be used to search for
an existing open TCP/UDP socket and its attributes that can be associated with a
packet. It looks for an established or non-zero bound listening socket (possibly
with a non-local address).</p>
<p>Thanks to the structure of the <code class="highlighter-rouge">nf_tables</code> framework this effort resulted in a
simple implementation which can be used in ip, ip6 and inet tables.</p>
<h3 id="main-patches-related-to-this-part">Main patches related to this part</h3>
<h4 id="nft">nft</h4>
<ul>
<li><a href="http://git.netfilter.org/nftables/commit/?id=a02f8c3f6456e9a84a6c3117f2539376b152ba1f">src: Introduce socket matching</a></li>
<li><a href="http://git.netfilter.org/nftables/commit/?id=5d22fc81fe27e24dba7a78743318a401353e506b">test: py: Add test cases for socket matching</a></li>
<li><a href="http://git.netfilter.org/nftables/commit/?id=6cebd48bfc365b39cb65b6b46cee3f0482408202">doc: Add socket expression to man page</a></li>
<li><a href="http://git.netfilter.org/nftables/commit/?id=9ea0401e385e1dd3f1579a4e772aa876a5e21288">src: Expose socket mark via socket expression</a></li>
</ul>
<h4 id="libnftnl">libnftnl</h4>
<ul>
<li><a href="http://git.netfilter.org/libnftnl/commit/?id=038d226f2e6cc132de151cc295ea2e4b8805659a">src: Add support for native socket matching</a></li>
<li><a href="http://git.netfilter.org/libnftnl/commit/?id=18454d929ac351c0b52ad8454a3905663198658d">socket: Expose socket mark via socket expression</a></li>
</ul>
<h4 id="kernel">kernel</h4>
<ul>
<li><a href="https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/commit/?id=554ced0a6e2946562c20d9fffdbaf2aa7da36b1b">netfilter: <code class="highlighter-rouge">nf_tables</code>: add support for native socket matching</a></li>
<li><a href="https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/commit/?id=7d25f8851a2c03319bfa8e56bb40bde2c4621392">netfilter: <code class="highlighter-rouge">nft_socket</code>: Expose socket mark</a></li>
</ul>
<h2 id="tproxy-statement-implementation">Tproxy statement implementation</h2>
<p>This part was already a bit more complex. I had to extract core functions from
the <code class="highlighter-rouge">xt_TPROXY</code> implementation and reproduce its use in nft. Now it can be used
to redirect packets to a local socket without changing the packet header in any
way. This works in ip, ip6 and inet tables, too.</p>
<h3 id="main-patches-related-to-tproxy-statement">Main patches related to tproxy statement</h3>
<h4 id="nft-1">nft</h4>
<ul>
<li><a href="http://git.netfilter.org/nftables/commit/?id=2be1d52644cf77bb2634fb504a265da480c5e901">src: Add tproxy support</a></li>
<li><a href="http://git.netfilter.org/nftables/commit/?id=7dfc5e6586286d72cc294a4a33acbbaa8d2f73ac">tests: py: Add test cases for tproxy support</a></li>
<li><a href="http://git.netfilter.org/nftables/commit/?id=029d9b3c16ae2354b6397c325a8dc389c67d970b">doc: Add tproxy statement to man page</a></li>
</ul>
<h4 id="libnftnl-1">libnftnl</h4>
<ul>
<li><a href="http://git.netfilter.org/libnftnl/commit/?id=c5a98195523416e4fa21fc649b4c61ef653eec32">expr: Add tproxy support</a></li>
</ul>
<h4 id="kernel-1">kernel</h4>
<ul>
<li><a href="https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/commit/?id=45ca4e0cf2734f8cc14b43e47c23618215abf1b8">netfilter: Libify <code class="highlighter-rouge">xt_TPROXY</code></a></li>
<li><a href="https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/commit/?id=5711b4e89319c2912f20b2a4f371c1525fc9551d">netfilter: <code class="highlighter-rouge">nf_tproxy</code>: fix possible non-linear access to transport header</a></li>
<li><a href="https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/commit/?id=f286586df68e7733a8e651098401f139dc2e17f4">netfilter: <code class="highlighter-rouge">nft_tproxy</code>: Move <code class="highlighter-rouge">nf_tproxy_assign_sock()</code> to <code class="highlighter-rouge">nf_tproxy.h</code></a></li>
<li><a href="https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/commit/?id=4ed8eb6570a49931c705512060acd50058d61616">netfilter: <code class="highlighter-rouge">nf_tables</code>: Add native tproxy support</a></li>
</ul>
<h2 id="other-contributions-and-summary">Other contributions and summary</h2>
<p>Beyond my project proposal I also implemented some fixes to the socket and tproxy
part of the kernel, the nft testing infrastructure and I started to implement
textual representation of standard priorities in the nft tool to make life
easier for sysadmins.</p>
<p>To get all my contributions check the following links:</p>
<ul>
<li><a href="http://git.netfilter.org/nftables/log/?qt=grep&q=ecklm94">nft patches</a></li>
<li><a href="http://git.netfilter.org/libnftnl/log/?qt=grep&q=ecklm94">libnftnl patches</a></li>
<li><a href="https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git/log/?qt=grep&q=ecklm94">kernel patches</a></li>
<li><a href="http://patchwork.ozlabs.org/patch/953128/">Set/print standard chain prios with textual names (to be accepted)</a></li>
</ul>Here I’d like to summarise my efforts until the publishing day of this post in the netfilter project as part of the Google Summer of Code 2018 program. This will also serve as a product submission which Google requires as a final part of the program.GSoC 2018 proposal2018-08-03T00:00:00+00:002018-08-03T00:00:00+00:00http://gsoc-blog.ecklm.com/gsoc-2018-proposal<p>I publish this post so that we have all my GSoC 2018 related things together
here. Here you can read my original proposal which was submitted to the
program. You can also read it on the Summer of Code project page.</p>
<h1 id="transparent-proxy-refactoring">Transparent proxy refactoring</h1>
<h2 id="abstarct">Abstarct</h2>
<p>Nftables is the successor of {ip,ip6,arp,eb}tables as a network filtering and
classification framework. Its enhancement is to unite all the tools for
different protocols and provide a complex interface to manage them.</p>
<p>My plan is to refactor the iptables implementation of transparent proxying
, and move its functionality to an external library which can then be used by
nftables, too.</p>
<h2 id="about-me">About me</h2>
<p>I am a first-year masters student in Computer Engineering at Budapest University
of Technology and Informatics, and my main specialisation is computer
networking. My experience includes volunteering in a networking-related IT
group, and working at smaller companies, where I did network and system
administration (Cisco and Linux), and network function implementation like DDNS
service and VoIP measuring instrument (the last one was my BSc thesis).</p>
<p>Apart from Cisco, Linux is an important platform for me, the implemented
services mentioned above were made for Linux environment. During my works I
used open-source projects and libraries, however I do not have any notable
contribution yet.</p>
<h3 id="contact-info">Contact info</h3>
<ul>
<li><strong>Full name:</strong> Máté Eckl</li>
<li><strong>Email:</strong> xxxxxxxxxxxxxxxxx</li>
<li><strong>Phone:</strong> xxxxxxxxxxxx</li>
</ul>
<h2 id="benefits-to-community">Benefits to Community</h2>
<p>As iptables was created much before nftables, most of the filtering and
manipulation framework functionality was originaly implemented in iptables’ code
and thus it was iptables-specific.</p>
<p>TPROXY is still one of these.</p>
<p>With my commitment, it would become possible to use already implemented
functionality from both iptables and nftables, thus transparent proxying
would become available for the new framework, too.
This can later be extended with cli support which finally offers the transparent
proxying to the users.</p>
<h2 id="deliverables">Deliverables</h2>
<p>To deliver full functionality, support should be implemented in different parts,
which are the following:</p>
<ul>
<li>Functionality should be extracted from iptables</li>
<li>Nftables kernel module should be implemented using the extracted library</li>
</ul>
<hr />
<ul>
<li>Libnftnl should be extended to support the new functionality</li>
<li>Nft cli frontend should use the libnftnl interface to offer transparent
proxying to users.</li>
</ul>
<p>The items below the line are considered optional in case the obligatory part is
completed much before the final deadline. I only schedule the obligatory part
in my working plan.</p>
<p>Documentation will be produced in a way that the community supports (probably
different for every part), and if there is no such way (they do not document
their code, and they do not accept my way to do it), it will be omitted.</p>
<h2 id="proposal-timeline">Proposal Timeline</h2>
<p>During the coding, I plan to go on holiday for 2-3 days (weekend excluded),
during which I will only be available by mobile phone. I do not know exactly
when, but I will try to schedule it right after one of the evaluation periods.</p>
<h3 id="before-23-april">Before 23 April</h3>
<ul>
<li>Investigate differences between transparent proxy and destiation nat</li>
<li>Set up a fail-proof development environment</li>
<li>Try transparent proxying with iptables</li>
</ul>
<h3 id="23-april--14-may-community-bonding">23 April – 14 May (Community bonding)</h3>
<ul>
<li>Test network preparation</li>
<li>Use case investigation</li>
<li>Preparing traffic generation to help investigation</li>
<li>Discussing workflow with the mentor(s)</li>
<li>Get to know to contribution conventions more deeply</li>
<li>More detailed investigation of relevant netfilter and iptables codebase</li>
</ul>
<h3 id="14-may--11-june-until-first-mid-term-evaluation">14 May – 11 June (Until first mid-term evaluation)</h3>
<ul>
<li>Identify code to be extracted</li>
<li>Plan the structure and interface of the library</li>
<li>Create the library and make iptables module use it</li>
<li>Constant documentation</li>
</ul>
<h3 id="11-june--9-july-until-second-mid-term-evaluation">11 June – 9 July (Until second mid-term evaluation)</h3>
<ul>
<li>Submit patches to the community, fix bugs if any, iptables module
refactoring should be accepted by the end (maximum of two weeks)</li>
<li>
<p>Plan the layout of the nftables kernel module, to fit a possible
user interface design.</p>
</li>
<li>Start nftables module implementation</li>
</ul>
<h3 id="9--24-july">9 – 24 July</h3>
<ul>
<li>Implement the nftables kernel module</li>
<li>Consulting with the mentor(s) before aproaching the final deadline</li>
</ul>
<h3 id="24-july--6-august">24 July – 6 August</h3>
<p>This last time slot should be used for <strong>one</strong> of the following:</p>
<ul>
<li>Catching up with delayed work</li>
<li>Code refinement</li>
<li>Implementation of parts from the optional section mentioned above.</li>
<li>Help the community in bug hunting</li>
</ul>I publish this post so that we have all my GSoC 2018 related things together here. Here you can read my original proposal which was submitted to the program. You can also read it on the Summer of Code project page.Linux local routes and policy routing intro2018-07-04T00:00:00+00:002018-07-04T00:00:00+00:00http://gsoc-blog.ecklm.com/linux-local-routes-and-policy-routing-intro<p>In the <a href="https://git.kernel.org/pub/scm/Linux/kernel/git/pablo/nf-next.git/tree/Documentation/networking/tproxy.txt">tproxy documentation</a>
there is a description about how to set up transparent proxying with the help of
iptables and polcy routing. As this is quite a special use-case I met some
questions wich are not so obvious, neither are the answers. In this post you can
read a little intro about this topic.</p>
<p>The relevant commands are the following:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>iptables <span class="nt">-t</span> mangle <span class="nt">-N</span> DIVERT
<span class="nv">$ </span>iptables <span class="nt">-t</span> mangle <span class="nt">-A</span> PREROUTING <span class="nt">-p</span> tcp <span class="nt">-m</span> socket <span class="nt">-j</span> DIVERT
<span class="nv">$ </span>iptables <span class="nt">-t</span> mangle <span class="nt">-A</span> DIVERT <span class="nt">-j</span> MARK <span class="nt">--set-mark</span> 1
<span class="nv">$ </span>iptables <span class="nt">-t</span> mangle <span class="nt">-A</span> DIVERT <span class="nt">-j</span> ACCEPT
<span class="nv">$ </span>ip rule add fwmark 1 lookup 100
<span class="nv">$ </span>ip route add <span class="nb">local </span>0.0.0.0/0 dev lo table 100
</code></pre></div></div>
<p>These operations have to be made so that the sockets assigned to non-local IP
can receive network packets.</p>
<p>When I was preparing my test environment two questions occured to me: <em>How does
the kernel not know that there is a socket assigned to this address and not
forward packets to it? And how does it work for sockets that have addresses that
are assigned to any of the local iterface addresses?</em></p>
<p>The necessary information to answer these questions are in the man pages
ip-route(8) and ip-rule(8), but it took some time for me to find out where I can
read about this and how the pieces are connected. So let’s have a look at the
starting points of such a discovery.</p>
<p>We have to take a tour around multiple routing tables in Linux. There is a
routing table called ‘main’ which is known by most of the sysadmins. It stores
the default route and all external routes by default. Although there is more
under the surface, which is the answer to the second question. All the local
interface and broadcast adresses are set up in the ‘local’ routing table by the
OS. You can list them with <code class="highlighter-rouge">ip route show table local</code>. For most of the cases
the users do not need to manipulate this table so it is mostly unknown and
untouched by human beings, however, as such it is just as important as the
‘main’ table.</p>
<p>Actually the answer to the first question is also here. The local table is
handled by the OS and by default it only adds addresses of the interfaces to it.
Creating a new socket does not insert any rule in the local table. This way, if
we use a non-local address, the approppriate routing table entry will be
missing. There is certainly some ways to solve transparent proxy support with
only these two tables, but it would include routing table hacking from the proxy
program, or some other ugly solution. Hence we use policy routing to do it.</p>
<p>Policy routing in the Linux kernel is enabled by the <code class="highlighter-rouge">IP_MULTIPLE_TABLES</code> and
<code class="highlighter-rouge">IPV6_MULTIPLE_TABLES</code> kernel config parameters which are enabled by default for
desktop and server environments. The most common tool to use this ability is
the <code class="highlighter-rouge">ip rule</code> command. In its man page it describes the structure and priorities
and how it implements policy routing. In our example we use the packet mark as a
selector and as we mark all packets that have a corresponding socket, it just
works fine. (<strong>Note:</strong> I strugled a bit with what <code class="highlighter-rouge">lookup</code> means as it is not
documented. It is supposedly a deprecated command but it is equivalent to
<code class="highlighter-rouge">table</code> as it can be seen in the <a href="https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/iprule.c?id=f686f764682745daf6a93b0a6330ba42a961f858#n583">source code</a>.)</p>
<p>Basically not much more is necessary to understand what happens behind the
scenes and it is quite the same with IPv6. Read the manuals, and happy networking!</p>In the tproxy documentation there is a description about how to set up transparent proxying with the help of iptables and polcy routing. As this is quite a special use-case I met some questions wich are not so obvious, neither are the answers. In this post you can read a little intro about this topic.Iptables REDIRECT vs. DNAT vs. TPROXY2018-05-02T00:00:00+00:002018-05-02T00:00:00+00:00http://gsoc-blog.ecklm.com/iptables-redirect-vs.-dnat-vs.-tproxy<p>As getting closer to the task itself (which is to extract the transparent proxy
support from iptables to be available from nftables as well), different
solutions come up which serve similar purposes and the difference between them
is not trivial.</p>
<p>In what they are similar is that we want the clients not to connect directly to
a service (server), but have a network entity (node) in between.</p>
<p>The following figure about my test topology will be useful to discuss the
differences.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> +---+ .1 .2 +---+
(proxy) | X |-----------------| Z | (server)
+---+ 10.0.4.0/24 +---+
| .101
|
| 10.0.3.0/24
|
| .1
+---+
| Y | (client)
+---+
</code></pre></div></div>
<p>Now see the different possibilities grouped by the iptables target that makes
them available.</p>
<p>There are some solutions for redirecting traffic with the help of the Linux
kernel and iptables. These are DNAT, REDIRECT and TPROXY.</p>
<h2 id="dnat">DNAT</h2>
<p>This target in the iptables nat table makes the function of destination nat
available.</p>
<p>This is a quite known concept, if you are familiar with basic networking, you
have probably met this. Low-cost home routers usually call it port forwarding.</p>
<p>What it does is changing the destination addresss (and destination port) to
given values <em>before the routing decision is made</em>, and makes the routing
decision be based on the new parameters. It is an important point here that it
<em>actually modifies</em> the IP (and TCP) header and requires connection tracking to
work, as the reply packets should be matched and translated back.</p>
<h3 id="see-an-example-use-case">See an example use-case</h3>
<p>Regarding the figure above, we might want to make node <code class="highlighter-rouge">Z</code> reachable from the
internet without giving public IP address to it. A reason for this can be the
lack of sufficient addresses or security considerations (however NAT is not
considered to be security solution as far as I know). The result is a service
that runs in a private network being accessible through a public gateway.</p>
<p>Lets see an example with iptables:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[X]$ iptables --table nat --append PREROUTING --protocol tcp --dport 80 --jump DNAT --to-destination 10.0.4.2
</code></pre></div></div>
<p>This command makes every incoming packets to <code class="highlighter-rouge">X</code> on port 80 to be forwarded
towards <code class="highlighter-rouge">Z</code> with a changed IP header.</p>
<p><strong>Note</strong> that, this solution needs ip forwarding to be enabled in the kernel as
actual routing is done.</p>
<h3 id="who-knows-who">Who knows who?</h3>
<p>In this scenario, <code class="highlighter-rouge">Z</code> knows that the sender of the request is <code class="highlighter-rouge">Y</code>, and thinks
that <code class="highlighter-rouge">Y</code> sent the packet directly to it. <code class="highlighter-rouge">Z</code> therefore will send response
packets to <code class="highlighter-rouge">Y</code>. Connection tracking is necessary to translate the adress of <code class="highlighter-rouge">Z</code>
to that of <code class="highlighter-rouge">X</code> in the response as the source address.</p>
<p><code class="highlighter-rouge">Y</code> on the other hand does not know that it is communicating with <code class="highlighter-rouge">Z</code>, it
believes that <code class="highlighter-rouge">X</code> receives and replies to its request.</p>
<h3 id="who-configures-this-solution">Who configures this solution?</h3>
<p>When DNAT is used, it is configured by the administrator of the service. He/she
wants to hide <code class="highlighter-rouge">Z</code> behind <code class="highlighter-rouge">X</code> for whatever reason.</p>
<h2 id="redirect">REDIRECT</h2>
<p>This iptables target cannot be associated with a well-known networking solution.
It is like a special DNAT rule where the new destination address is mandatorily
the IP address of the receiving interface.</p>
<p>Here, incoming packets matching the rule have their destination address changed
to the receiving interface’s address and optionally their destination port
changed to a specific or a random port (depending on the command). Similar to
DNAT, the IP (and probably transport layer) header <em>is modified</em>.</p>
<h3 id="see-an-example-use-case-1">See an example use-case</h3>
<p>For instance you have a flask server listening on port 8080, but the standard
HTTP port is 80, so you are receiving requests to this port. The following
iptables role will redirect all tcp packets with the destination port of 80 to
port 8080.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[X]$ iptables --table nat --append PREROUTING --protocol tcp --dport 80 --jump REDIRECT --to-ports 8080
</code></pre></div></div>
<p>What is its benefit over DNAT? When I want to redirect traffic on the local
host, DNAT needs the destination address to be added which makes it hard to
maintain if the interface addresses can change. Redirect does not need a
specific IP address to work, so it is more flexible.</p>
<p><strong>Note</strong> that, using REDIRECT leaves node <code class="highlighter-rouge">Z</code> untuched, so the service should
run on <code class="highlighter-rouge">X</code>.</p>
<h3 id="who-knows-who-1">Who knows who?</h3>
<p>In this scenario <code class="highlighter-rouge">Y</code> does not necessarily know who it is communicating with, <code class="highlighter-rouge">X</code>
knows <code class="highlighter-rouge">Y</code> and <code class="highlighter-rouge">Z</code> is not part of the communication at all.</p>
<h3 id="who-configures-this-solution-1">Who configures this solution?</h3>
<p>REDIRECT is also configured by the administrator of the service, the users know
nothing about this.</p>
<h2 id="tproxy">TPROXY</h2>
<p>This solution is different from the other two in more aspects.</p>
<p>First, let’s see what a proxy is in general. Proxies are nodes/softwares that
are used to stand between the client and the service. The client connects to the
proxy server which then connects to the server through a distinct connection.
This method can be used for various purposes like hiding my own identity from
the server, activity logging or response caching etc.</p>
<p>The first significant difference can be catched here. While DNAT and REDIRECT
had everything done in the kernel, being a proxy means running a specific
software that does the task, the kernel “only” needs to support this.</p>
<p>A proxy can be transparent or non-transparent.</p>
<p>An example to non-transparent proxy can be when you set the address and other
data of the proxy server in your web browser or any other client. In this case
you know about the proxy service and you explicitly configure your device to use
it.</p>
<p>On the other hand, a transparent proxy is invisible for the client. No
configuration is needed on the OS of the client, the network parameters can be
configured to use this solution.</p>
<h3 id="see-an-example-use-case-2">See an example use-case</h3>
<p>Establishing a transparent proxy is a bit more difficult than the other two
solutions. There is a documentation available
<a href="https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/Documentation/networking/tproxy.txt">here</a>.
Detailed description of what happens here is out of the scope of the actual post
(I will probably write a separate one about this later).</p>
<p>However, I’d like to describe what can be seen at different points of the
network without any config, after point 1. and point 2. As this is my main
interest, it will be a bit more dateiled than the ones before.</p>
<p>To test this functionality I used <a href="https://git.breakpoint.cc/cgit/fw/tcprdr.git/">this program</a>.</p>
<h4 id="without-any-config">Without any config</h4>
<p>After the tcprdr program is compiled, the following commands should be run on
different nodes (the order on <code class="highlighter-rouge">Y</code> should go last).</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Z]$ nc --listen --local-port=80
[X]$ ./tcprdr 50080 10.0.4.2 80
[Y]$ telnet 10.0.3.101 50080
</code></pre></div></div>
<p>This solution does not require kernel support. Without <code class="highlighter-rouge">-t</code> ot <code class="highlighter-rouge">-T</code> flags,
tcprdr does not set <code class="highlighter-rouge">IP_TRANSPARENT</code> option on any of the sockets, so it
basically copies bytes from one socket to another.</p>
<p>For now it is nothing special, if run <code class="highlighter-rouge">ss</code> (formerly <code class="highlighter-rouge">netstat</code>) on <code class="highlighter-rouge">X</code>, you see
the following:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[X]$ ss --tcp --numeric --processes
StateRecv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB0 0 10.0.3.101:50080 10.0.3.1:41088 users:(("tcprdr",pid=460,fd=4))
ESTAB0 0 10.0.4.1:46190 10.0.4.2:80 users:(("tcprdr",pid=460,fd=5))
</code></pre></div></div>
<p>So tcprdr copies bytes from the firs socket to the second and vice versa.</p>
<h4 id="with-policy-routing-point-1">With policy routing (point 1.)</h4>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Z]$ nc --listen --local-port=80
# A static route is also necessary (later described).
[Z]$ ip route add 10.0.3.101 via 10.0.4.1
[X]$ ./tcprdr -T 50080 10.0.4.2 80
[Y]$ telnet 10.0.3.101 50080
</code></pre></div></div>
<p>Adding the <code class="highlighter-rouge">-T</code> flag to <code class="highlighter-rouge">tcprdr</code> enables <code class="highlighter-rouge">IP_TRANSPARENT</code> option on the outgoing
socket. The output of <code class="highlighter-rouge">ss</code> is the following:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[X]$ ss --tcp --numeric --processes
StateRecv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB0 0 10.0.3.101:50080 10.0.3.1:41144 users:(("tcprdr",pid=533,fd=4))
ESTAB0 0 10.0.3.1:41144 10.0.4.2:80 users:(("tcprdr",pid=533,fd=5))
</code></pre></div></div>
<p>This is still without the TPROXY support of the kernel.</p>
<p>The difference here is that <code class="highlighter-rouge">X</code> uses the IP and TCP source parameters from <code class="highlighter-rouge">Y</code>
as its own, so <code class="highlighter-rouge">Z</code> receives packets with the source address of <code class="highlighter-rouge">Y</code>. The static
route is necessary to be able to respond to these packets.</p>
<p>The policy routing makes it possible for <code class="highlighter-rouge">tcprdr</code> to hanle packets in response.
This circumstance may be later described in a separate post.</p>
<h4 id="with-tproxy-support-point-2">With TPROXY support (point 2.)</h4>
<p>Adding the iptables rule makes it possible for the proxy application (<code class="highlighter-rouge">tpcrdr</code>
in our case) to receive packets with the destination port other than what the
listening socket is bound to. Also application-level support is necessary, the
<code class="highlighter-rouge">-t</code> flag sets the <code class="highlighter-rouge">IP_TRANSPARENT</code> option on the listening socket. This makes
the following scenario possible.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Z]$ nc --listen --local-port=80
[X]$ ./tcprdr -t -T 50080 10.0.4.2 80
[Y]$ telnet 10.0.3.101 80
</code></pre></div></div>
<p>The sockets on <code class="highlighter-rouge">X</code> are the following now:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[X]$ ss --tcp --numeric --processes
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 10.0.3.101:80 10.0.3.1:33104 users:(("tcprdr", pid=634,fd=4))
ESTAB 0 0 10.0.3.1:33104 10.0.4.2:80 users:(("tcprdr", pid=634,fd=5))
[X]$ ss --tcp --numeric --processes --listening
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN0 20 0.0.0.0:50080 0.0.0.0:* users:(("tcprdr",pid=560,fd=3))
</code></pre></div></div>
<p>As the example shows, <code class="highlighter-rouge">X</code> receives packets destined to a port that it is not
listening to. TPROXY target makes this possible.</p>
<p>Why is it different from REDIRECT? Because TPROXY does not modify the transport
layer header, it only forwards the packet without any modification. It also
does not require connection tracking as the local port for the connection socket
will be the original destination port.</p>
<p>The benefit of this function over the first two is that no exact port matching
is necessary, so the users do not have to explicitly send SSH
traffic to port 50080 to reach the service, just to mention an example.</p>
<p><em>There is also a fourth scenario, when only the <code class="highlighter-rouge">-t</code> flag is set, that means <code class="highlighter-rouge">X</code>
uses its own address to communicate with <code class="highlighter-rouge">Z</code>.</em></p>
<p>To sum up this a bit: <code class="highlighter-rouge">IP_TRANSPARENT</code> socket option makes it possible to
assign an IP address to a socket regardless of whether it is assigned to any of
the network interfaces on our machine or not. None of these require connection
tracking nor ip forwarding option set in the kernel, because the packets are not
forwarded, their payload is only copied from one socket to another.</p>
<p>To decide which socket we want to set transparent, the circumstances should be
known, for now it is enough that it is possible, and the iptables support is
only necessary for the listening socket to work.</p>
<h3 id="who-knows-who-2">Who knows who?</h3>
<p>The answer is different on all three of the described scenarios.</p>
<p>In the firs case, both <code class="highlighter-rouge">Y</code> and <code class="highlighter-rouge">Z</code> knows <code class="highlighter-rouge">X</code> but not each other.</p>
<p>In the second one, <code class="highlighter-rouge">Y</code> knows <code class="highlighter-rouge">X</code> and <code class="highlighter-rouge">Z</code> knows <code class="highlighter-rouge">Y</code> but not <code class="highlighter-rouge">X</code>, as the source
address of the socket between <code class="highlighter-rouge">X</code> and <code class="highlighter-rouge">Z</code> is that of <code class="highlighter-rouge">Y</code>.</p>
<p>From this point of view, the third option is the same as the second one, only
the destination port from <code class="highlighter-rouge">Y</code> can vary.</p>
<p>In the forth scenario, we have the same knowledge as in the first, only the
destination port from <code class="highlighter-rouge">Y</code> can vary.</p>
<h3 id="who-configures-this-solution-2">Who configures this solution?</h3>
<p>There is another difference from the other solutions here. A proxy is something
that the service provide of the client configures to track and/or improve the
internet access of the client.</p>As getting closer to the task itself (which is to extract the transparent proxy support from iptables to be available from nftables as well), different solutions come up which serve similar purposes and the difference between them is not trivial.Blog intro2018-04-30T00:00:00+00:002018-04-30T00:00:00+00:00http://gsoc-blog.ecklm.com/blog-intro<p>Dear reader,</p>
<p>This is the first post of this blog, and I would like to introduce, what this
blog will be about, what kind of information you will find here, and what is the
motivation behing all this.</p>
<p>Fortunately my project proposal has been accepted to be carried out as part of
the Google Summer of Code 2018 programme. As a consequence I will be working on
the nftables project, which is a possible successor of iptables. The public
details on my project are available
<a href="https://summerofcode.withgoogle.com/organizations/5444605277896704/#5597779292848128">here</a></p>
<p>This is an opportunity for me to learn <em>a lot</em> about parts of Linux networking
that are usually out of scope for most of the users and administrators (and have
been for me, too), and also get involved in kernel-level development with the help
of the community.
I have been dealing with it intensively for only some days, and I have already
leant a lot.</p>
<p>During my former tries and education I found it quite hard to get clear about
things that are not trivial at all and in dozens of cases it is hard to even ask
the correct question.
Even Google needs the appropriate keywords to show you what you want to know.</p>
<p>As I now have the support of the community to deal with a specific set of
problems, I thought it would be benefficial to share what and how I learn during
the summer to help those trying to get to know to these subjects, and probably
to get closer to netfilter development.</p>
<p>This blog is thus going to serve both documentational and educational purposes
about what problems I face, and what extra information is necessary to resolve
them. Of course, all descriptions are based on my level of knowledge, although I
will try to describe things on a way that is beneficial to those who are less
avare of this area than I am.</p>
<p>Hope to help with this to some people.</p>
<p>Regards,
Máté</p>
<p><em>Ps.: This blog is also a documentation for myself not to forget about what I
have already learnt once :). This attitude can result in otherwise useless
information in some posts.</em></p>Dear reader,