<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.mogosanu.ro &#187; iptables</title>
	<atom:link href="http://blog.mogosanu.ro/tag/iptables/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mogosanu.ro</link>
	<description>the tutorial blog</description>
	<lastBuildDate>Sat, 03 Apr 2010 07:26:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>nat loopback, partea a ii-a</title>
		<link>http://blog.mogosanu.ro/shell-scripting/nat-loopback-partea-a-ii-a/</link>
		<comments>http://blog.mogosanu.ro/shell-scripting/nat-loopback-partea-a-ii-a/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 12:48:23 +0000</pubDate>
		<dc:creator>spyked</dc:creator>
				<category><![CDATA[shell scripting]]></category>
		<category><![CDATA[/etc/crontab]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[expect]]></category>
		<category><![CDATA[iptables]]></category>
		<category><![CDATA[nat loopback]]></category>
		<category><![CDATA[wget]]></category>

		<guid isPermaLink="false">http://blog.mogosanu.ro/?p=87</guid>
		<description><![CDATA[În prima parte am discutat diverse metode de a accesa adresa (în cele mai multe cazuri, unul sau mai multe nume de site-uri interpretate de către un server web intern) externă a unei rețele din interiorul acesteia și ne-am oprit asupra cazulului particular în care router-ul are linux cu iptables instalat și putem adăuga două [...]]]></description>
			<content:encoded><![CDATA[<p>În <a href="http://blog.mogosanu.ro/retelistica/nat-loopback-partea-i/">prima parte</a> am discutat diverse metode de a accesa adresa (în cele mai multe cazuri, unul sau mai multe nume de site-uri interpretate de către un server web intern) externă a unei rețele din interiorul acesteia și ne-am oprit asupra cazulului particular în care router-ul are linux cu iptables instalat și putem adăuga două reguli suplimentare tabelei NAT.</p>
<p>Ne confruntăm aici cu o problemă: la restartarea router-ului, configurarea adițională se va pierde. În plus, softul acestuia nu permite adăugarea unor script-uri care să se execute la bootare și nici modificarea celor existente. Vom presupune că varianta schimbării firmware-ului (variantă care presupune riscul transformării router-ului într-o bucată de plastic bună de aruncat la gunoi, în cel mai rău caz) nu ne interesează, astfel că trebuie să transmitem totuși comenzile din exterior, prin telnet. Am presupus din capul locului că avem în rețea o mașină care rulează tot timpul, identificată prin <em>$server_ip</em>; adresa router-ului în rețea este <em>$router_ip</em>.</p>
<p>Automatizarea transmisiei de comenzi de la server către router se va face în două etape: prima, conceperea unui script care să comunice cu router-ul și a doua, verificarea la momente de timp prestabilite dacă regulile de NAT Loopback sunt în tabelă.</p>
<p><strong>1.Script-ul de introducere a regulilor în NAT-ul router-ului</strong></p>
<p>Pentru a putea comunica cu router-ul, trebuie în primul rând să știm cum va arăta shell-ul în sesiunea de telnet cu utilizatorul. De exemplu, pe modem-ul subsemnatului, ZTE931, prima dată se va cere user-ul și parola prin linii de forma „Login: ” și „Password: ”. Apoi va fi afișat un shell identificat prin string-ul „&gt; ”, iar după ce introduc comanda „sh” va fi afișat un alt shell, dat de „#”. Apoi, după fiecare comandă eu voi aștepta „#” de la modem.</p>
<p>Această comunicație poate fi automatizată folosind utilitarul <strong>expect</strong>, a cărui pagină de manual vă recomand să o consultați. Script-ul se va rula într-un shell special; se așteaptă răspunsuri de la o entitate folosind comanda <em>expect</em>, iar răspunsurile se trimit cu <em>send</em>. Mai concret, script-ul de update al tabelei NAT al router-ului va arăta astfel:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/expect -f</span>
spawn telnet <span style="color: #007800;">$router_ip</span> <span style="color: #666666; font-style: italic;">#deschid sesiunea telnet</span>
expect <span style="color: #ff0000;">&quot;Login: &quot;</span>
send <span style="color: #660033;">--</span> <span style="color: #ff0000;">&quot;admin<span style="color: #000099; font-weight: bold;">\r</span>&quot;</span>
expect <span style="color: #ff0000;">&quot;Password: &quot;</span>
send <span style="color: #660033;">--</span> <span style="color: #ff0000;">&quot;passgoeshere<span style="color: #000099; font-weight: bold;">\r</span>&quot;</span>
expect <span style="color: #ff0000;">&quot;&gt; &quot;</span>
send <span style="color: #660033;">--</span> <span style="color: #ff0000;">&quot;sh<span style="color: #000099; font-weight: bold;">\r</span>&quot;</span> <span style="color: #666666; font-style: italic;">#deschid shell pentru comenzi</span>
expect <span style="color: #ff0000;">&quot;#&quot;</span>
send <span style="color: #660033;">--</span> <span style="color: #ff0000;">&quot;iptables -t nat -A PREROUTING -d <span style="color: #007800;">$external_ip</span> -p tcp --dport 80 <span style="color: #000099; font-weight: bold;">\
</span>      -j DNAT --to <span style="color: #007800;">$server_ip</span>; iptables -t nat -A POSTROUTING -d <span style="color: #007800;">$server_ip</span> <span style="color: #000099; font-weight: bold;">\
</span>      -s 192.168.0.0/24 -p tcp --dport 80 -j SNAT --to <span style="color: #007800;">$router_ip</span>&quot;</span>
expect <span style="color: #ff0000;">&quot;#&quot;</span>
send <span style="color: #660033;">--</span> <span style="color: #ff0000;">&quot;exit<span style="color: #000099; font-weight: bold;">\r</span>&quot;</span> <span style="color: #666666; font-style: italic;">#inchiderea sesiunii</span>
expect <span style="color: #ff0000;">&quot;&gt; &quot;</span>
send <span style="color: #660033;">--</span> <span style="color: #ff0000;">&quot;exit<span style="color: #000099; font-weight: bold;">\r</span>&quot;</span></pre></div></div>

<p>Rularea acestui script bash/expect va substitui deschiderea unei sesiuni interactive și introducerea manuală a comenzilor de către utilizator. Script-ul poate fi executat de pe oricare mașină din rețeaua internă, după restartarea router-ului. Vom presupune că am numit acest script <strong>natloop</strong> și l-am salvat pe server-ul având adresa <em>$server_ip</em>, în directorul /router.</p>
<p><strong>2.Verificarea automată a existenței NAT Loopback</strong></p>
<p>Această problemă poate fi rezolvată în mai multe moduri. Unul din aceste moduri e chiar folosirea <em>expect</em> pentru verificarea tabelei NAT și update în cazul în care regulile nu există. Dar din moment ce am presupus că rezolvăm forward-ul către un server web, vom da o soluție un pic mai simplă: am spus că în cazul în care router-ul nu satisface NAT Loopback pe portul 80, vom fi direcționați către interfața web a acestuia. Un <strong>wget</strong> pe <em>$router_ip</em> (sau pe <em>$external_ip</em>, atunci când nu există NAT Loopback) va întoarce cel mai probabil un cod de eroare 401 (forbidden, deoarece nu au fost specificate user-ul și parola pentru sesiune). În schimb, dacă iau <em>$nume_domeniu</em> cu <em>wget</em>, voi primi 200 (eventual după câteva redirectări). Codul script-ului <strong>pingip</strong> (nume ales complet aleator, salvat probabil tot în /router) este următorul:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #007800;">mesaj</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #007800;">$adr_domeniu</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-i</span> <span style="color: #ff0000;">&quot;HTTP request&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">tail</span> <span style="color: #660033;">-n</span> <span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">cut</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot; &quot;</span> -f6<span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$mesaj</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #000000;">200</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$(date)</span> <span style="color: #007800;">$mesaj</span> Failed&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>router<span style="color: #000000; font-weight: bold;">/</span>nat.log
    <span style="color: #000000; font-weight: bold;">/</span>router<span style="color: #000000; font-weight: bold;">/</span>natloop
<span style="color: #000000; font-weight: bold;">else</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$(date)</span> <span style="color: #007800;">$mesaj</span> Merge&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>router<span style="color: #000000; font-weight: bold;">/</span>nat.log
<span style="color: #000000; font-weight: bold;">fi</span></pre></div></div>

<p>Vom diseca întâi prima linie, care are rolul de a lua efectiv codul întors de cererea HTTP și a-l salva în variabila <em>$mesaj</em>. Practic, generez un flux de string-uri, executând <em>wget</em> pe una din adresele web externe ale server-ului și redirectând <em>stderr</em> către <em>stdout</em>. Acest flux îl filtrez cu un <em>grep</em> (doresc să știu doar codul întors de pagină, iar acesta are în față „HTTP Request&#8221;) și iau ultima linie, care va conține cel mai probabil ori 200 ori 401. Împart linia în coloane (după spații) folosind <em>cut</em> și iau a șasea coloană, care reprezintă codul propriu-zis.</p>
<p>Apoi tot ce fac este să verific dacă am un cod diferit de 200 și să rulez <em>natloop</em> în acest caz. Pentru a monitoriza activitatea script-ului, îl pun să scrie timestamp-ul și un mesaj (cod plus stare) într-un fișier pentru logging. Ce mai rămâne este adăugarea unei linii în /etc/crontab, pentru a executa script-ul nostru la anumite intervale de timp (eu l-am pus să facă verificarea la fiecare cinci minute, de exemplu).</p>
<p>Trebuie remarcat că e posibil ca acest exercițiu de scripting să nu dea întotdeauna rezultate corecte. Problema în sine e destul de complicată, deoarece presupune interdependența mai multor noduri din rețea (chiar și așa, putând fi complicată și mai mult în funcție de diverși factori). Personal, sugerez cititorului să înțeleagă și să se documenteze bine înainte să ruleze oricare din comenzile menționate aici (e de ajuns un comment și voi oferi lămuriri suplimentare dacă e nevoie). De asemenea, dacă cineva vine cu o soluție mai bună, sunt numai ochi.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mogosanu.ro/shell-scripting/nat-loopback-partea-a-ii-a/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>nat loopback, partea i</title>
		<link>http://blog.mogosanu.ro/retelistica/nat-loopback-partea-i/</link>
		<comments>http://blog.mogosanu.ro/retelistica/nat-loopback-partea-i/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 13:48:12 +0000</pubDate>
		<dc:creator>spyked</dc:creator>
				<category><![CDATA[\\Retelistica]]></category>
		<category><![CDATA[/etc/hosts]]></category>
		<category><![CDATA[bridging]]></category>
		<category><![CDATA[busybox]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[iptables]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nat loopback]]></category>

		<guid isPermaLink="false">http://bogdan.mogosanu.ro/?p=46</guid>
		<description><![CDATA[Înainte să descriem problema propriu-zisă (sau pentru a o descrie mai ușor), vom explica pe scurt conceptul de NAT Loopback: Se dă o rețea locală formată dintr-un număr arbitrar de mașini și un router/modem/NAT box/server DHCP care deține o adresă IP din Internet. Vom nota adresa externă a router-ului cu $external_ip și pe cea internă [...]]]></description>
			<content:encoded><![CDATA[<p>Înainte să descriem problema propriu-zisă (sau pentru a o descrie mai ușor), vom explica pe scurt conceptul de NAT Loopback: Se dă o rețea locală formată dintr-un număr arbitrar de mașini și un router/modem/NAT box/server DHCP care deține o adresă IP din Internet. Vom nota adresa externă a router-ului cu <em>$external_ip</em> și pe cea internă cu <em>$router_ip</em>. Presupunem că rețeaua are adrese în range-ul 192.168.0.0/24 și conține un server cu un IP oarecare, pe care îl vom nota cu <em>$server_ip</em>. Vom considera și o mașină oarecare din rețeaua internă, notată cu <em>$client_ip</em>. Menționăm că NAT box-ul are un port oarecare (sau un range de port-uri), 80 să presupunem, forwardat către server.</p>
<p>Să presupunem că <em>$client_ip</em> dorește să acceseze <em>$external_ip</em> &#8211; sau un nume de domeniu asociat IP-ului, pe care îl vom nota cu <em>$nume_domeniu</em> &#8211; pe portul 80. Ce se va întâmpla în acel moment? Dacă router-ul dispune de <em>NAT Loopback</em> (și are facilitatea activată), atunci el va face forwardarea din interior către <em>$server_ip</em>, interpretarea acestuia fiind „<em>$client_ip</em>, deși este din interiorul rețelei, vrea să acceseze server-ul intern ca și cum s-ar fi conectat din exteriorul rețelei&#8221;. În caz contrar, router-ul nu va face forwardarea, ci va răspunde la fel ca în cazul în care este accesat pe <em>$router_ip:80</em>, deci va interpreta cererea astfel: „<em>$client_ip</em> dorește să se conecteze la mine pe portul 80”.</p>
<p>Anumite routere, cum ar fi modelele <a href="http://en.wikipedia.org/wiki/Linksys_WRT54G_series">WRT54G</a> de la Linksys pot să facă NAT Loopback (eventual cu firmware-ul DD-WRT instalat). Alte routere/modem-uri fac asta implicit (fără ca utilizatorul să poată specifica alt comportament), iar altele nu știu deloc să facă NAT Loopback, de exemplu modem-urile VDSL de la Romtelecom (de acestea din urmă lovindu-se subsemnatul). Există câteva workaround-uri posibile pentru ca un site din rețeaua internă să poată fi accesat :</p>
<ol>
<li><strong>Modificarea fișierului &#8220;hosts&#8221;</strong>: soluție viabilă pentru un server care nu găzduiește un număr mare de domenii și pentru o rețea cu un număr mic și fix de calculatoare (Atenție! Pentru clienți interni mobili: laptop-uri, netbook-uri etc., soluția poate cauza probleme la conectarea ulterioară din exterior). Pe mașina (sau mașinile, presupunând că sunt mai multe) client, în /etc/hosts (diverse variante Unix) sau în windows\system32\drivers\hosts se va seta un alias de forma:

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">$server_ip</span> <span style="color: #007800;">$nume_domeniu</span></pre></div></div>

<p>Unde <em>$nume_domeniu</em> este numele domeniului pe care dorim să îl accesăm. Se va adăuga câte un astfel de alias pentru fiecare domeniu hostat de către mașina server.</li>
<li><strong>Configurarea unui server DNS</strong>, soluție destul de complicată încât să nu o explic aici. Pe scurt, se poate configura un server de nume special pentru rețeaua internă, care să directeze cererile pentru domeniile locale către <em>$server_ip</em> și să rezolve celelalte cereri normal. Pentru asta însă, toate mașinile din rețeaua internă trebuie configurate în așa fel încât să rezolve toate cererile NS prin acel server.</li>
<li>(pentru modem-uri) <strong>Configurarea în bridge cu un router capabil de NAT Loopback </strong>sau (pentru routere) <strong>înlocuirea cu un router capabil de NAT Loopback</strong>. Totuși, dacă soluția asta ar fi fost așa simplă, nu începeam articolul de față.</li>
<li>(pentru routere/modem-uri cu Linux/Unix și iptables) <strong>Configurarea iptables în interfața router-ului</strong>: soluția la care a recurs subsemnatul, asta fiindcă, pur întâmplător, modem-ul Romtelecom are un firmware bazat pe Busybox, un distro de linux pentru dispozitive embedded, accesibil prin telnet. În acest caz, <a href="http://www.netfilter.org/documentation/HOWTO/NAT-HOWTO-10.html">documentația iptables</a> menționează o metodă interesantă de configurare a NAT-ului (pentru versiunea 2.4 a kernel-ului de linux, dar aparent funcționează și pe 2.6): se face forwardarea prin NAT a tuturor cererilor venite din rețeaua internă către <em>$server_ip</em> prin modificarea în chain-ul PREROUTING a adresei destinație și, pentru ca pachetele să știe pe unde să se întoarcă, schimbarea în POSTROUTING a adresei sursă (inițial <em>$client_ip</em>) cu adresa router-ului. Cel puțin teoretic, router-ul ar trebui să știe să intermedieze conexiunea între client-ul intern și server. În mai puține cuvinte, comenzile de iptables sunt:

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> PREROUTING <span style="color: #660033;">-d</span> <span style="color: #007800;">$external_ip</span> <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">80</span> <span style="color: #660033;">-j</span> DNAT <span style="color: #660033;">--to</span> <span style="color: #007800;">$server_ip</span>
$ iptables <span style="color: #660033;">-t</span> nat <span style="color: #660033;">-A</span> POSTROUTING <span style="color: #660033;">-d</span> <span style="color: #007800;">$server_ip</span> <span style="color: #660033;">-s</span> 192.168.0.0<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">24</span> <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">80</span> \
 <span style="color: #660033;">-j</span> SNAT <span style="color: #660033;">--to</span> <span style="color: #007800;">$router_ip</span> <span style="color: #666666; font-style: italic;">#se inlocuieste 192.168.0.0/24 in functie de retea</span></pre></div></div>

</li>
</ol>
<p>Primele două metode scot complet router-ul din ecuație. Astfel, dacă se întâmplă să schimbăm router-ul cu altul, această modificare nu ar trebui să afecteze cu nimic configurația creată anterior. A treia metodă e cea mai radicală, rezolvă cele mai multe probleme, dar este și cea mai scumpă.</p>
<p>Ultima metodă ar trebui să transforme router-ul nostru problemă într-unul capabil să facă <em>NAT Loopback</em>. Singura mare problemă este aceea că cele două comenzi nu sunt persistente. La fiecare restartare a router-ului, trebuie să ne conectăm prin telnet la acesta și să dăm copy/paste la cele două comenzi, fapt ce poate deveni destul de iritant la un moment dat (ce ne facem dacă suntem în concediu și colegii vor să acceseze un site de pe server-ul intern?).</p>
<p>În partea a doua a tutorial-ului vom discuta despre automatizarea task-ului de updatare a tabelei de NAT pe un modem/router cu Busybox (aceasta putându-se generaliza și pentru alte distribuții de Linux).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mogosanu.ro/retelistica/nat-loopback-partea-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

