كيفية إعادة توجيه المنافذ Forward Ports عبر بوابة لينكس Linux Gateway باستخدام IPTables


kinan mawed

NAT، أو نقل عنوان الشبكة network address translation، عبارة عن مصطلح عام لإدارة الرُّزَم packets من أجل إعادة توجيهها إلى عنوان بديل، وهو يُستخدم عادةً للسماح لحركة مرور البيانات traffic بتجاوز حدود الشبكة، يمتلك المُضيف host الذي يُطبِّق NAT نفاذًا إلى شبكتين أو أكثر بشكل نموذجي وهو مُعَد لنقل حركة مرور البيانات بينها.

إعادة توجيه المنافذ Port forwarding هو عمليّة إعادة توجيه الطلبات لمنفذ مُعيَّن إلى مُضيف آخر، شبكة، أو منفذ. وبينما تقوم هذه العمليّة بتعديل وجهة الرُّزَم أثناء نقلها، فهي تُعتبَر نوع من عمليّات NAT.

ports-forwarding-iptables.png

سنشرح في هذا الدرس كيفيّة استخدام iptables لإعادة توجيه المنافذ إلى مضيفين خلف جدار ناري باستخدام تقنيات NAT، يكون هذا مفيدًا في حال قمنا بإعداد شبكة خاصّة Private Network ولا زلنا نريد السماح لبعض حركة مرور البيانات بالمرور عبر جهاز مُحدّد كبوّابة gateway، سنستخدم مُضيفين اثنين يعملان على نظام Ubuntu لتوضيح هذا.

المتطلبات الأساسية والأهداف

لمتابعة هذا الدّرس تحتاج إلى مُضيفين اثنين يعملان على نظام Ubuntu في نفس مركز البيانات مع تمكين الشبكات الخاصّة private networking، نحتاج إلى إعداد حساب مُستخدِم غير جذري non-root مع صلاحيّات sudo على كل من هذين الجهازين، تستطيع معرفة كيفيّة إعداد مُستخدِم مع صلاحيّات sudo باتّباع درس الإعداد الأولي لخادوم Ubuntu.

سيعمل المُضيف الأول كجدار ناري ومُوجِّه router لأجل الشبكة الخاصّة، ولأغراض توضيحيّة سيكون المُضيف الثاني مُعدًّا مع خادوم ويب قابل للوصول فقط باستخدام واجهته الخاصّة، سنقوم بإعداد جهاز الجدار الناري ليُعيد توجيه الطلبات التي يتلقّاها على واجهته العامّة إلى خادوم الويب حيث ستصل إلى واجهته الخاصّة.

تفاصيل المضيف

نحتاج قبل البدء أن نعرف الواجهات والعناوين التي يتم استخدامها من قِبَل كلا الخادمين لدينا.

العثور على تفاصيل شبكتنا

للحصول على تفاصيل أنظمتنا نبدأ بإيجاد واجهات شبكاتنا Network Interfaces، نستطيع العثور على الواجهات والعناوين المرتبطة بها على أجهزتنا بكتابة:

ip -4 addr show scope global
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 198.51.100.45/18 brd 45.55.191.255 scope global eth0
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.1.5/16 brd 10.132.255.255 scope global eth1
       valid_lft forever preferred_lft forever

يُظهِر الخَرْج output السّابق واجهتين (eth0 و eth1) والعناوين المُخصّصة لكل منهما (192.51.100.45 و 192.168.1.5 على الترتيب)، ولمعرفة أيّ الواجهتين هي الواجهة العامّة نكتب:

ip route show | grep default
default via 111.111.111.111 dev eth0

تكون الواجهة الظاهرة أمامنا (eth0 في هذا المثال) هي الواجهة المُتصلة إلى بوّابتنا الافتراضيّة، وهي بكل تأكيد واجهتنا العامّة.

قم بإيجاد هذه القيم على كل جهاز لديك واستخدمها للمتابعة مع هذا الدّرس بشكل صحيح.

عينة بيانات من أجل هذا الدرس

لكي نجعل متابعة هذا الدّرس أسهل سنستخدم العناوين الوهميّة وتعيينات الواجهة التالية، قم بوضع القيم الخاص بك بدلًا من هذه القيم:

تفاصيل شبكة خادوم الويب:

  • عنوان IP العام Public IP Address: 203.0.113.2
  • عنوان IP الخاص Private IP Address: 192.0.2.2
  • الواجهة العامّة Public Interface: eth0
  • الواجهة الخاصّة Private Interface: eth1

تفاصيل شبكة الجدار الناري:

  • عنوان IP العام Public IP Address: 203.0.113.15
  • عنوان IP الخاص Private IP Address: 192.0.2.15
  • الواجهة العامّة Public Interface: eth0
  • الواجهة الخاصّة Private Interface: eth1

إعداد خادوم الويب

سنبدأ بإعداد مُضيف خادوم الويب، نقوم بتسجيل الدخول كمستخدم sudo للبدء.

تثبيت Nginx

الخطوة الأولى التي سنقوم بها هي تثبيت Nginx على مُضيف خادوم الويب لدينا وقفله بحيث يستمع فقط إلى واجهته الخاصّة، يجعلنا هذا متأكدين من أنّ خادوم الويب لن يكون متوفّرًا إلّا إذا ضبطنا إعادة توجيه المنافذ بشكل صحيح.

نبدأ بتحديث الذاكرة المؤقتة للحزم المحليّة local package cache باستخدام الأمر apt لتنزيل وتثبيت Nginx:

webserver $ sudo apt-get update
webserver $ sudo apt-get install nginx

تقييد Nginx إلى الشبكة الخاصة

بعد تثبيت Nginx نقوم بفتح ملف إعدادات كتلة block الخادوم الافتراضيّة للتأكد من أنّه يستمع فقط إلى واجهته الخاصّة، نفتح الملف عن طريق الأمر التالي:

webserver $ sudo nano /etc/nginx/sites-enabled/default

نبحث بداخله عن الأمر التوجيهي listen، ينبغي أن نجده في سطرين متتاليين في أعلى ملف الإعدادات:

etc/nginx/sites-enabled/default/

server {
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;

  . . .
}

نقوم عند الأمر التوجيهي listen الأول بإضافة عنوان IP الخاص لخادوم الويب لدينا مع نقطتين قبل 80 لنُخبِر Nginx أن يستمع فقط إلى واجهته الخاصّة، سنوضّح في هذا الدّرس إعادة توجيه IPv4 فقط، لذا نستطيع إزالة الأمر التوجيهي listen الثاني المُعَد من أجل IPv6.

سنقوم في مثالنا بتعديل الأمر التوجيهي listen بحيث يبدو كما يلي:

etc/nginx/sites-enabled/default/

server {
  listen 192.0.2.2:80 default_server;

  . . .
}

عند الانتهاء نحفظ الملف ونغلقه، نختبر الملف بحثًا عن أخطاء الصياغة syntax بكتابة ما يلي:

webserver $ sudo nginx -t

إن لم تظهر أيّة أخطاء نُعيد تشغيل خادوم Nginx لتمكين الإعدادات الجديدة:

webserver $ sudo service nginx restart

التحقق من تقييد الشبكة Network Restriction

من المُفيد عند هذه النقطة التحقّق من مستوى النفاذ الذي نملكه لخادوم الويب لدينا.

إن قمنا بمحاولة النفاذ لخادوم الويب عبر واجهته الخاصّة من خلال خادوم الجدار الناري firewall ينبغي أن ينجح هذا:

firewall $ curl --connect-timeout 5 192.0.2.2
<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to nginx!</title>
    <style>
      body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
      }
    </style>
  </head>

  <body>
    <h1>Welcome to nginx!</h1>
    . . .

أمّا إن قمنا باستخدام الواجهة العامّة سنجد أنّنا لن نستطيع الاتصال:

firewall $ curl --connect-timeout 5 203.0.113.2
curl: (7) Failed to connect to 203.0.113.2 port 80: Connection refused

وهو بالضبط ما نتوقّع حدوثه.

إعداد الجدار الناري لإعادة توجيه المنفذ 80

نستطيع الآن العمل على تنفيذ إعادة توجيه المنافذ على جهاز الجدار الناري.

تمكين إعادة التوجيه في النواة Kernel

الأمر الأول الذي يجب فعله هو تمكين إعادة التوجيه على مستوى النّواة، تكون إعادة التوجيه غير مُشغَّلة في مُعظم الأنظمة.

ولتشغيل إعادة توجيه المنافذ لأجل هذه الجلسة فقط نكتب:

firewall $ echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

ولتشغيل إعادة توجيه المنافذ بشكل دائم ينبغي علينا تحرير الملف etc/sysctl.conf/، نفتح الملف بصلاحيّات sudo بكتابة:

firewall $ sudo nano /etc/sysctl.conf

نبحث بداخله عن السطر التالي ونقوم بإزالة التعليق uncomment عنه:

etc/sysctl.conf/

net.ipv4.ip_forward=1

عند الانتهاء نحفظ الملف ونغلقه، نقوم بتطبيق الإعدادات في هذا الملف بكتابة ما يلي:

firewall $ sudo sysctl -p
firewall $ sudo sysctl --system

إعداد الجدار الناري الأساسي

سنستخدم الجدار الناري الموجود في هذا الدّرس كإطار عمل أساسي من أجل القواعد، قم بتنفيذ التعليمات في درس كيفية إعداد جدارٍ ناريّ باستخدام iptables، وبعد الانتهاء يجب أن تكون قد:

  • قمت بتثبيت iptables-persistent
  • حفظت مجموعة القواعد الافتراضيّة في etc/iptables/rules.v4/
  • تعلّمت كيفيّة إضافة أو ضبط القواعد عن طريق تحرير ملف القواعد أو باستخدام الأمر iptables

بعد أن تقوم بإعداد الجدار الناري الأساسي أكمل الخطوات التالية لكي تستطيع ضبطه من أجل إعادة توجيه المنافذ.

إضافة قواعد إعادة التوجيه

نريد أن نضبط جدارنا الناري بحيث تتم إعادة توجيه حركة مرور البيانات traffic المُتدفّقة لواجهتنا العامّة (eth0) إلى واجهتنا الخاصّة (eth1).

يمتلك جدارنا الناري الأساسي السلسلة FORWARD مُعدّة افتراضيًّا لكي تستبعد DROP حركة مرور البيانات، نحتاج لإضافة قواعد تسمح لنا بإعادة توجيه الاتصالات لخادوم الويب لدينا، ولأغراض أمنية سنقوم بتحديد هذا بشكل مُحكَم بحيث يتم فقط السماح للاتصالات التي نرغب بإعادة توجيهها.

سنقبل في السلسلة FORWARD الاتصالات الجديدة المتجهة للمنفذ 80 والقادمة من واجهتنا العامة مُغادرةً إلى واجهتنا الخاصة، يتم تحديد الاتصالات الجديدة بواسطة اللاحقة conntrack ويتم تمثيلها بشكل خاص بواسطة رُزمة TCP SYN:

firewall $ sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT

سيسمح هذا للرزمة الأولى المعنيّة بإنشاء الاتصال بالعبور من خلال الجدار الناري، نحتاج أيضًا للسماح بأي حركة مرور بيانات لاحقة في كلا الاتجاهين والتي تنتج عن هذا الاتصال، نكتب ما يلي للسماح بحركة مرور البيانات التي تُنشئ هذا الاتصال ESTABLISHED والمتعلّقة به RLEATED بين واجهاتنا الخاصّة والعامة:

firewall $ iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
firewall $ iptables -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

بإمكاننا إعادة التحقّق من أنّ سياساتنا على السلسلة FORWARD هي الاستبعاد DROP بكتابة ما يلي:

firewall $ sudo iptables -P FORWARD DROP

عند هذه النقطة سمحنا بحركة مرور بيانات مُحدّدة بين واجهاتنا الخاصّة والعامّة بالمرور من خلال الجدار الناري لدينا، ومع ذلك لم نقم بضبط القواعد التي تُخبِر iptables فعليًّا كيف يقوم بنقل وتوجيه حركة مرور البيانات.

إضافة قواعد NAT لتوجيه الرزم بشكل صحيح

سنضيف الآن القواعد التي تُخبِر iptables كيف يقوم بتوجيه حركة مرور بياناتنا، نحتاج لتنفيذ عمليتين منفصلتين من أجل أن يقوم iptables بتغيير الرُّزَم بشكل صحيح بحيث يتمكّن العملاء من التواصل مع خادوم الويب.

تحدث العمليّة الأولى التي تُدعى DNAT في السلسلة PREROUTING من جدول nat، وهي عمليّة تقوم بتبديل عنوان وجهة الرُّزَم لتمكينها من التوجه بشكل صحيح عندما تمر بين الشبكات، سيتصل العملاء على الشبكة العامّة إلى خادوم الجدار الناري لدينا بدون أن يعلموا عن بُنية الشبكة الخاصّة لدينا، نحتاج لتبديل عنوان الوجهة لكل رُزمة بحيث تعلم عند إرسالها خارج شبكتنا الخاصّة كيف تصل بشكل صحيح إلى خادوم الويب.

بما أنّنا نقوم فقط بإعداد إعادة توجيه المنافذ ولا نقوم بعمل NAT على كل رُزمة تصطدم بجدارنا الناري فيجب علينا أن نُطابِق المنفذ 80 في قاعدتنا، سنقوم بمطابقة الرُّزَم التي تستهدف المنفذ 80 إلى عنوان IP الخاص لخادوم الويب لدينا (192.0.2.2 في مثالنا):

firewall $ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.0.2.2

يهتم هذا بنصف الحل، فينبغي الآن أن يتم توجيه الرُّزَم بشكل صحيح إلى خادوم الويب لدينا، ومع ذلك فإنّ الرُّزَم لا تزال تملك العنوان الأصلي للعميل كعنوان مصدر، وسيحاول الخادوم إرسال الرد مباشرة إلى ذلك العنوان، ممّا يجعل من المستحيل تأسيس اتصال TCP قانوني.

نحتاج من أجل ضبط التوجيه المناسب أن نقوم بتعديل عنوان المصدر للرُزَم عندما تغادر الجدار الناري في طريقها إلى خادوم الويب، يجب علينا تعديل عنوان المصدر وتغييره إلى عنوان IP الخاص لخادوم الجدار الناري لدينا (في مثالنا 192.0.2.15)، سيتم عندها إرسال الرّد إلى الجدار الناري والذي يستطيع إعادة توجيهه إلى العميل كما هو متوقّع.

ولتمكين هذه الوظيفة سنضيف قاعدة إلى سلسلة POSTROUTING من جدول nat، والتي يتم تقييمها مباشرة قبل إرسال الرُّزَم على الشبكة، سنطابق الرُّزَم الموجّهة إلى خادوم الويب عن طريق عنوان IP والمنفذ:

firewall $ sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp --dport 80 -d 192.0.2.2 -j SNAT --to-source 192.0.2.15

حالما يتم إعداد هذه القاعدة ينبغي أن يصبح خادوم الويب لدينا قابل للنفاذ عن طريق توجيه متصفّح الويب لدينا إلى العنوان العام لجهاز الخادوم الناري:

curl 203.0.113.15
<!DOCTYPE html>
<html>
  <head>
    <title>Welcome to nginx!</title>
    <style>
      body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
      }
    </style>
  </head>

  <body>
    <h1>Welcome to nginx!</h1>
    . . .

اكتمل هنا إعداد إعادة توجيه المنافذ.

ضبط مجموعة القواعد الدائمة

نستطيع الآن بعد أن قمنا بإعداد إعادة توجيه المنافذ أن نحفظه في مجموعة قواعد دائمة.

إن لم تكن تهتم بفقدان التعليقات الموجودة في مجموعة القواعد الحالية لديك فاستخدم الخدمة iptables-persistent لحفظ قواعدك:

firewall $ sudo service iptables-persistent save

إن كنت ترغب بالحفاظ على التعليقات في ملفّك، فقم بفتحه وتحريره يدويًّا:

firewall $ sudo nano /etc/iptables/rules.v4

سنحتاج إلى ضبط الإعدادات في الجدول filter من أجل قواعد السلسلة FORWARD التي تمّت إضافتها، يجب علينا أيضًا ضبط القسم الذي يقوم بإعداد الجدول nat كي نستطيع إضافة القواعد PREROUTING و POSTROUTING، سيبدو هذا في مثالنا مُشابِهًا لما يلي:

etc/iptables/rules.v4/

*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]

# Acceptable UDP traffic

# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT

# Acceptable ICMP traffic

# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT

# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP

# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable

# Rules to forward port 80 to our web server

# Web server network details:

# * Public IP Address: 203.0.113.2
# * Private IP Address: 192.0.2.2
# * Public Interface: eth0
# * Private Interface: eth1
#
# Firewall network details:
#
# * Public IP Address: 203.0.113.15
# * Private IP Address: 192.0.2.15
# * Public Interface: eth0
# * Private Interface: eth1
-A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# End of Forward filtering rules

# Commit the changes

COMMIT

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# Rules to translate requests for port 80 of the public interface
# so that we can forward correctly to the web server using the
# private interface.

# Web server network details:

# * Public IP Address: 203.0.113.2
# * Private IP Address: 192.0.2.2
# * Public Interface: eth0
# * Private Interface: eth1
#
# Firewall network details:
#
# * Public IP Address: 203.0.113.15
# * Private IP Address: 192.0.2.15
# * Public Interface: eth0
# * Private Interface: eth1
-A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.0.2.2
-A POSTROUTING -d 192.0.2.2 -o eth1 -p tcp --dport 80 -j SNAT --to-source 192.0.2.15
# End of NAT translations for web server traffic
COMMIT

*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

قم بحفظ الملف وأغلقه بعد إضافة ما سبق وضبط القيم لكي تنطبق على بيئة شبكتك الخاصّة.

نختبر صياغة ملف القواعد لدينا بكتابة:

firewall $ sudo iptables-restore -t < /etc/iptables/rules.v4

إن لم يتم اكتشاف أيّة أخطاء نقوم بتحميل مجموعة القواعد:

firewall $ sudo service iptables-persistent reload

نختبر أنّ خادوم الويب لدينا لا يزال قابل للنفاذ من خلال عنوان IP العالم للجدار النّاري:

firewall $ curl 203.0.113.15

ينبغي لهذا أن يعمل كما عمل سابقًا.

الخاتمة

ينبغي الآن أن نكون متآلفين مع إعادة توجيه المنافذ على خادوم لينِكس باستخدام iptables، تتضمّن العملية السماح بإعادة التوجيه على مستوى النّواة، إعداد النفاذ للسماح بإعادة التوجيه لحركة مرور البيانات لمنافذ مُحدّدة بين واجهتين على نظام الجدار النّاري، وضبط قواعد NAT بحيث يُمكِن توجيه الرُّزَم بشكل صحيح، ربّما تبدو هذه عمليّة صعبة، ولكنّها تُوضّح أيضًا مرونة إطار عمل ترشيح الرُّزَم netfilter وجدار iptables النّاري، يُمكِن استخدام هذا لتمويه بُنية الشبكة الخاصّة لدينا مع السمّاح بحركة مرور البيانات للخدمات بالمرور بشكل حر عبر بوّابة جهاز الجدار النّاري.

ترجمة -وبتصرّف- لـ How To Forward Ports through a Linux Gateway with Iptables لصاحبه Justin Ellingwood.

bacula-ubuntu-backup.png





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن