سادگی زیباست...

بررسی انواع معماری های سیستم عامل و برنامه های سیستمی و روشهای توسعه آنها

سادگی زیباست...

بررسی انواع معماری های سیستم عامل و برنامه های سیستمی و روشهای توسعه آنها

سادگی زیباست...

۲ مطلب در بهمن ۱۳۹۲ ثبت شده است

کتابخانه ZMQ، یک کتابخانه برای ارتباطات غیر همگام با سرعت بالا است. این کتابخانه برای بسیاری از زبانهای برنامه نویسی دارای API میباشد و بسیار کارایی راحتی دارد. این کتابخانه یک صف پیغام (message queue) ایجاد میکند، اما بر خلاف میان افزارهای بر مبنای پیغام (message based middleware) نیازمند یک دلال پیغام (message broker) نمیباشد. این کتابخانه بسیار مشابه به یک API سوکت است.
معماری های اصلی موجود در ZMQ موارد زیر است:
  • Request-Reply: اتصال مجموعه ای از سرویس گیرنده ها به مجموعه ای از سرویس دهنده ها.
  • Publish-Subscribe: اتصال مجموعه ای از توزیع کنندگان به مجموعه ای از دریافت کنندگان. این یک مدل توزیع داده است.
  • Push-pull: یک مدل fan out/fan in که در این مدل یک صف پیغام به تمام دریافت کنندگان پوش میشود.
  • exclusive pair: اتصال دو سوکت به همدیگر به صورت جفت خاص
خود کتابخانه zmq در مورد امنیت امکانات خاصی ندارد. به منظور فراهم آوردن ارتباط امن بین دو سیستم (یا پردازش) میتوان از پروتکل SSH استفاده کرد. با استفاده از پروتکل SSH میتوان بین دو سیستم تونل ارتباطی برقرار کرد (همان کاری که برای رد کردن محدودیت اینترنتی انجام میشود).
فرض کنید که معماری زیر را داشته باشیم:
  • سیستم A دارای یک پردازش که به پورت 5556 گوش میدهد و خود سیستم دارای آدرس 192.168.10.245 است.
import zmq
import time
import sys

port = "5556"
if len(sys.argv) > 1:
    port =  sys.argv[1]
    int(port)

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:%s" % port)

while True:
    #  Wait for next request from client
    message = socket.recv()
    print "Received request: ", message
    time.sleep (1)  
    socket.send("World from %s" % port)
  • سیستم B که به سیستم A متصل خواهد شد.
import zmq
from zmq import ssh
import sys
import paramiko

port = "5557"
if len(sys.argv) > 1:
    port =  sys.argv[1]
    int(port)

if len(sys.argv) > 2:
    port1 =  sys.argv[2]
    int(port1)

context = zmq.Context()
print "Connecting to server..."
socket = context.socket(zmq.REQ)
socket.connect ("tcp://192.168.10.245:%s" % port)

#  Do 10 requests, waiting each time for a response
for request in range (1,10):
    print "Sending request ", request,"..."
    socket.send ("Hello")
    #  Get the reply.
    message = socket.recv()
    print "Received reply ", request, "[", message, "]"
این سیستم میتواند به سادگی توسط zmq پیاده سازی شود.
در قدم بعدی میتوان با استفاده از تونل، ارتباط بین را امن کرد. در این مرحله یک تونل به صورت دستی ایجاد میشود. با دستور زیر یک ارتباط تونلی بین پورت 5557 سیستم B با پورت 5556 سیستم B توسط SSH برقرار میشود.
ssh -L 127.0.0.1:5557:localhost:5556 user@192.168.10.245 -N

بعد از وارد کردن دستور بالا در ترمینال کلمه عبور سیستم A پرسیده میشود. بعد از وارد کردن آن میتون ارتباط امن بین پردازش ها را داشته باشیم. کد برنامه ها به صورت زیر تغییر پیدا میکند:

سیستم A که نقش سرور را دارد:

import zmq
import time
import sys

port = "5556"
if len(sys.argv) > 1:
    port =  sys.argv[1]
    int(port)

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://127.0.0.1:%s" % port)

while True:
    #  Wait for next request from client
    message = socket.recv()
    print "Received request: ", message
    time.sleep (1)  
    socket.send("World from %s" % port)

کد سیستم B که نقش سرویس گیرنده دارد:

import zmq
from zmq import ssh
import sys
import paramiko

port = "5557"
if len(sys.argv) > 1:
    port =  sys.argv[1]
    int(port)

if len(sys.argv) > 2:
    port1 =  sys.argv[2]
    int(port1)

context = zmq.Context()
print "Connecting to server..."
socket = context.socket(zmq.REQ)
socket.connect ("tcp://127.0.0.1:%s" % port)

#  Do 10 requests, waiting each time for a response
for request in range (1,10):
    print "Sending request ", request,"..."
    socket.send ("Hello")
    #  Get the reply.
    message = socket.recv()
    print "Received reply ", request, "[", message, "]"

در کتابخانه pyzmq که یک پیاده سازی برای zmq است، یک گسترش بر روی اتصال zmq وجود دارد که همین کار اتصال تونل را انجام میدهد. کد نهایی به صورت زیر خواهد بود:

کد سیستم A تغییر نخواهد کرد و همان کد قسمت قبلی است

کد سیستم B به صورت زیر خواهد بود:

import zmq
from zmq import ssh
import sys
import paramiko

port = "5557"
if len(sys.argv) > 1:
    port =  sys.argv[1]
    int(port)

if len(sys.argv) > 2:
    port1 =  sys.argv[2]
    int(port1)

context = zmq.Context()
print "Connecting to server..."
socket = context.socket(zmq.REQ)
ssh.tunnel_connection(socket,"tcp://127.0.0.1:5556","user@192.168.10.245",password="111111")
if len(sys.argv) > 2:
    socket.connect ("tcp://192.168.10.245:%s" % port1)

#  Do 10 requests, waiting each time for a response
for request in range (1,10):
    print "Sending request ", request,"..."
    socket.send ("Hello")
    #  Get the reply.
    message = socket.recv()
    print "Received reply ", request, "[", message, "]"

۴ موافقین ۰ مخالفین ۰ ۱۳ بهمن ۹۲ ، ۲۱:۴۹
حامد شیخلو
هسته شماره 3.13 لینوکس منتشر شد. یکی از اصلیترین ویژگی های این نسخه، قرار دادن نسخه نهایی nftables بر روی آن است. این سیستم جایگزین سیستم های iptables, ip6tables,arptables, ebtables خواهد بود. نسخه قرار داده شده بر روی هسته 3.13 نسخه کامل نیست و ویژگی های اضافی به تدریج به آن اضافه خواهد شد.
سیستم nftables با یک دستورات خط فرمان nft همراه است. این دستور جایگزین فرمان iptables خواهد بود اما ظاهر کاملا متفاوتی خواهد داشت. در صورتی که با hptables کار کده باشید، این تغییر میتوان آزار دهنده باشد، اما یک لایه هماهنگ ساز برای تبدیل دستورات iptables به nftables وجود دارد.
متاسفانه مستندات کمی برای آشنایی با این سیستم وجود دارد، در این مطلب سعی میکنیم آشنایی اولیه با این سیستم پیدا کنیم.

بررسی مثالهایی برای آشنایی

فرض کنید که میخواهید بسته های خاصی را با iptables فیلتر کنید، در iptables دستورات زیر را خواهید نوشت.

iptables -A FORWARD -p tcp --dport 22 -j LOG
iptables -A FORWARD -p tcp --dport 22 -j DROP

با سیستم nftables دستور زیر را خواهید نوشت:

nft add rule filter forward tcp dport 22 log drop

فرض کنید که میخواهید بسته های چندین بسته را برای چندین پورت را فیلتر کنید و همچنین به نوع های خاص پروتکل icmpv6 اجازه عبود دهید. در iptables دستورات زیر را خواهید نوشت:

ip6tables -A INPUT -p tcp -m multiport --dports 23,80,443 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT

اما در nftables دستور زیر ر خواهید نوشت:

nft add rule ip6 filter input tcp dport {telnet, http, https} accept
nft add rule ip6 filter input icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept

mapping

یک ویژگی پیشرفته در nftables قابلیت مپ کردن است. این امکان وجود دارد که از داده هایی با اعواع مختلف استفاده کنیم و آنها را به هم مپ کنیم. برای مثال میتوان یک iface و مجموعه رول را به هم مرتبط کنیم. در مثال زیر زنجیره دستورات به نام low_sec و high_sec ساخته شده است.

# nft -i
nft> add map filter jump_map { type ifindex => verdict; }
nft> add element filter jump_map { eth0 => jump low_sec; }
nft> add element filter jump_map { eth1 => jump high_sec; }
nft> add rule filter input meta iif vmap @jump_map

در صورت نیاز به افزودن یک رابط شبکه، مثلا ppp1 دستور زیر را خواهیم نوشت:

nft> add element filter jump_map { ppp1 => jump low_sec; }

سرعت بروز رسانی و هسته

سیستم iptables با افزودن دستورات زیاد تر به حد زیادی دچار افت سرعت میشود. اما در سیستم جدیدتر nftables این کاهش سرعت وجود نخواهد داشت.

در سیستم iptables برای هر افزودن target یا match نیازمند ماژول و کامپایل دوباره کرنل هستیم. در سیستم nftables بیشتر وظایف در لایه کاربری انجام میشود که این مساله باعث کاهش نیاز به تغییرات هسته میشود. برای مثال ویژگی پشتیبانی از icmp6 با یک پچ قابل انجام است.

در مطلب بعدی به تغییرات معماری سیستم خواهیم پرداخت.

۱ موافقین ۰ مخالفین ۰ ۰۵ بهمن ۹۲ ، ۰۰:۳۵
حامد شیخلو