<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های امیر سلطانی</title>
        <link>https://virgool.io/feed/@m_59481059</link>
        <description>من یه عاشق دنیای دواپس و تکنولوژی ام که دنبال چالش های جدید و یادگیری همه چیزم</description>
        <language>fa</language>
        <pubDate>2026-06-16 09:31:33</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/2957999/avatar/BZOO3t.png?height=120&amp;width=120</url>
            <title>امیر سلطانی</title>
            <link>https://virgool.io/@m_59481059</link>
        </image>

                    <item>
                <title>آسیب پذیری لینوکس - از یک کاربر عادی تبدیل به یه یوزر root شو</title>
                <link>https://virgool.io/@m_59481059/linux-vulnerability-qdajsvjqcrqe-qdajsvjqcrqe</link>
                <description>سلام به همگی. اخیرا یک آسیب پذیری بسیار مهم (CVE-2026-31431) در لینوکس گزارش شده که عملا اگر شما هر سرور لینوکسی ای که داشته باشید باید kernel تون رو آپدیت کنید. حالا این آسیب پذیری چی هست؟اگر به طور خلاصه بگم شما با هر یوزری که تو لینوکس لاگین کردید میتونید تبدیل به یوزر root بشید :) . جالبه که این مورد امنیتی از سال 2017 بوده تو کرنل و خدا میدونه چنیدن نفر از این راه سوء استفاده کردن و issue نکردنش. ولی الان بعد از گذشت نزدیک به 9 سال این آسیب پذیری پیدا شده و تو بسیاری از Distro ها حل شده. فقط نیازه که شما ورژن کرنلتون رو آپدیت کنید تا همه چی گل و بلبل بشه.خب بیایین در مورد آسیب پذیری به صورت فنی صحبت کنیم.تو کرنل لینوکس ما یک قابلیت خفن داریم به اسم AF_ALG. این قابلیت به برنامه های User Space اجازه میده بدون اینکه تو دردسر بیفتن تو دل سخت افزار عملیات رمزنگاری رو انجام بدن. مثلا فرض کنید میخواید یک فایل بزرگ رو با AES رمزنگاری کنید. به جای اینکه خودتون توی برنامه تون الگوریتم رو پیاده کنید، میاید از این ساکت مخصوص استفاده میکنید که داده رو بفرسته به کرنل و کرنل عملیات رمزنگاری رو انجام بده.سال 2017 یه بهینه سازی خفن توی این بخش پیاده کردن. قبل از اینکه بگیم چی بود باید در مورد scatterlist حرف بزنیم . این یه فیچر خیلی باحله تو لینوکس. فرض کنید یه کتاب 100 صفحه ای میخوایید واسه اکبر آقا بفرستید. ولی چون حجم کتاب بالاست شما 33 صفحه اولو میذارید تو انباری و 33 تای بعدی تو آشپزخونه و 34 تای بعدی تو اتاق خواب و میایین از چیزی به عنوان scatterlist استفاده میکنید تا بدونید هر تیکه از کتاب کجاست. لینوکس هم دقیقا فایل های بزرگ رو وقتی میخواد تو مموری بذاره از این فیچر خودش استفاده میکنه. خب مهندس ها اومدن گفتن: چرا دوتا scatterlist مجزا برای ورودی و خروجی داشته باشیم؟ بذارین req-&gt;src رو برابر با req-&gt;dst قرار بدیم تا حافظه کمتری مصرف بشه و سرعت بره بالا. به نظر منطقی میاد نه؟ولی همه چی دقیقا از اینجا شروع میشهیه مثال با جزئیات بیشتر بزنیم. فرض کنید شما یه فایل دارید برای ذخیره رمز‌هاتون. مثلاً داخلش نوشتید:Gmail-Password: Akbar aghaو میخواید این فایل رو رمزنگاری کنید.قبل از 2017 لینوکس فایل اصلی رو از دیسک میاورد داخل RAM و بعد از رمزنگاری، خروجی رو داخل یه بخش دیگه از حافظه مینوشت. در نهایت همون بخش جدید حافظه روی دیسک نوشته میشد و جای فایل اولیه رو میگرفت. یعنی source و destination جدا بودن. حالا اگر موقع رمزنگاری ۴ بایت بیشتر هم نوشته میشد، معمولاً وارد فایل اصلی نمیشد چون خروجی داخل یه buffer جدا قرار داشت. اگر داده ای خارج از محدوده مورد انتظار نوشته میشد معمولا وارد buffer جداگانه خروجی میشد و مستقیما page cache فایل اصلی رو overwrite نمیکرد.ولی بعد از 2017 لینوکس برای performance بهتر از in-place encryption استفاده کرد. یعنی فایل رو از دیسک میاره داخل page cache یا RAM و عملیات رمزنگاری مستقیم روی همون بخش حافظه انجام میشه. در نتیجه خروجی روی همون memory اولیه overwrite میشه. مشکل CVE-2026-31431 این بود که اون ۴ بایت اضافه هم میتونست روی همون page cache نوشته بشه و باعث overwrite شدن page cache فایل های حساس مثل su بشه، بدون اینکه فایل واقعی روی دیسک تغییر کند. یعنی طرف میاد با سوء استفاده از crypto API میتونه page cache فایل دیگه‌ای رو overwrite کنه و اون سرویس رو (su) اجراش میکنه بلافاصله از روی رم و کلی validator check رو عملا دور بزنه :)))))))))مشکل دقیقا کجای کار خودش رو نشون داد؟الان دیگه ورودی و خروجی تو رمزنگاری یکی شده. اما یه الگوریتم خاص هست به اسم authencesn(hmac(sha256),cbc(aes)). این الگوریتم برای کارهایی که نیاز به Extended Sequence Number دارن، وسط کار مجبوره 4 بایت رو به عنوان فضای موقت در آفست assoclen + cryptlen بنویسه. یعنی یه &quot;خراش و دستگاری کوچولو&quot; میکنه تو حافظه.حالا فرض کنید کاربر از طریق splice() یک فایل رو به این ساکت رمزنگاری میده. به خاطر همون بهینه‌سازی 2017، tag page های فایل که توی page cache قرار دارن، با sg_chain() به خروجی scatterlist متصل میشن. یعنی خروجی رمزنگاری مستقیما رفته توی کش فایل اصلی توی حافظه. وقتی اون الگوریتم خاص میاد 4 بایت رو مینویسه، داره مینویسه رو حافظه کش شده فایل کاربر — بدون اینکه هیچ مجوز نوشتن روی اون فایل رو داشته باشه.چطور از این ۴ بایت میرسیم به root؟اینجا دقیقاً بخش جذاب ماجراست . ۴ بایت شاید کم به نظر برسد، ولی وقتی طرف کاردان باشه و بدونه دقیقا کجا و چه چیزی را overwrite کنه تغییر بده، همون ۴ بایت هم کافیه واسشمثلاً میتونه:page cache یک باینری setuid مثل /usr/bin/su یا sudo را تغییر دهد،یک شرط امنیتی یا branch حساس را patch کند،یا بخشی از control flow برنامه را دستکاری کند تا برنامه با دسترسی root کد دلخواه را اجرا کند.در CVE-2026-31431 مهاجم فایل واقعی روی دیسک را تغییر نمیده؛ فقط نسخه داخل RAM یا همان page cache را patch میکنه. بعد بلافاصله همان باینری آلوده داخل RAM اجرا میشود و privilege checkها bypass میشوند و attacker به root میرسد.فقط یک نکته: PoC کامل این آسیب‌پذیری اتفاقاً عمومی شده و exploit آن منتشر شده است؛ حتی Theori هم PoC رسمی منتشر کرده و چندین vendor و تیم امنیتی مستقل این vulnerability را تأیید کرده‌اند.حالا چطور مشکل رو حل کردن تو پچ های حال حاضر ؟ پچی که زدن برگشته همون بهینه‌سازی رو برداشته؟ نه دقیقا. اومدن گفتن: &quot;خوب تو این الگوریتم خاص که نیاز به scratch space داره، نباید اجازه بدیم خروجی با ورودی share بشه.&quot; یعنی رفع آسیب پذیری بدون از دست دادن کلیت بهینه‌سازی انجام شده. خیلی هوشمندانه است واقعاتو این لینک گیتهاب میتونید کد پایتون رو مشاهده کنید و خودتون هم تستش کنید.اگر نکته نظری داشتید خوشحال میشم برام بنویسیدتا نوشته ای دیگه عزت زیاد</description>
                <category>امیر سلطانی</category>
                <author>امیر سلطانی</author>
                <pubDate>Thu, 28 May 2026 17:40:18 +0330</pubDate>
            </item>
                    <item>
                <title>چطور میتونیم لاگ های سرویس هامون رو با Elastic Search و Vector مدیریت کنیم؟</title>
                <link>https://virgool.io/@m_59481059/%DA%86%D8%B7%D9%88%D8%B1-%D9%85%DB%8C%D8%AA%D9%88%D9%86%DB%8C%D9%85-%D9%84%D8%A7%DA%AF-%D9%87%D8%A7%DB%8C-%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D9%87%D8%A7%D9%85%D9%88%D9%86-%D8%B1%D9%88-%D8%A8%D8%A7-elastic-search-%D9%88-vector-%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%DA%A9%D9%86%DB%8C%D9%85-yyn5hru9etit</link>
                <description>سلام به همه. تو این نوشته میخوام یکمی در مورد اهمیت مدیریت لاگ ها صحبت کنیم و در آخر بیاییم و لاگ هارو از یه سرویس (تو این نوشته من access.log سرویس Nginx رو انتخاب کردم )بگیریم و بفرستیم به یه انبار مخصوص برای نگهداری لاگ هامون (Elastic Search) . خب اول کار اینم بگم این نوشته دو قسمت خواهد داشت . تو این قسمت پیاده سازی تماما خارج از کلاستر کوبر انجام میشه و تو قسمت بعدی همین سناریو رو میبریم تو دل کلاستر کوبر.خب؛ بیایید با این شروع کنیم که اصلا لاگ هارو چرا لازم داریم و چرا باید تو یه انبار تخصصی لاگ مثل الستیک سرچ نگهداری کنیم ازشون.لاگها مثل دزدگیر ماشین هستن. تا وقتی همه چیز اوکیه، کسی بهشون توجهی نمیکنه، اما همین که یه مشکل کوچیک پیش بیاد، همه میدونن که لاگها تنها چیزین که میتونن بگن «داستان از چه قرار بود؟!» . حالا چرا الستیک سرچ؟ یه مفهوم بسیار مهم در صنعت آی تی امروزی تو دنیا وجود داره و اونم اینه که در سرویسی که ساختی باید تو TPS های بالا بتونه عالی کار کنه و زیر لود سنگین جواب بده وگرنه سرهم کردن یه چیزی هنری نداره به اون صورت . اینا رو گفتیم که برسیم به این نکته که هنر کار ما زمانی مشخص میشه که بتونیم میلیارد ها لاگ رو مدیریت کنیم. حالا بیاییم در مورد دردسرهاش حرف بزنیم:حجم بزرگی از لاگ ها : یه سرور شلوغ میتونه تو یه روز چندین میلیارد خط لاگ تولید کنه. حالا سرویس های معروف مثل همین Nginx به طور Default داره Log Rotate میکنه ولی حتما یادتون باشه تو محیط عملیاتی حتما مولفه Log Rotating فراموش نشه که اگر بشه باعث مشکلات زیادی بعدا میشه. یه استاد اون ور آبی تو یوتیوب همیشه میگفت تو بحث آی تی همیشه اگه اولش به آخرش فکر کنی آخرش آدم خوشحال تری هستی :) . بریم سراغ مورد بعدی ؛مشکل جستجو بین حجم دیتای زیاد: پیدا کردن یه خطای خاص تو لاگها مثل این میمونه که تو یه کتابخونه تاریک با چراغ قوه دنبال یه خط تو یه کتاب بگردی!مدیریت لاگ های به درد نخور یا قدیمی: اگه لاگها رو پاک نکنی، دیسک پر میشه. اگه پاک کنی، شاید همون روز بهشون نیاز پیدا کنی!راه حل چیه؟الستیک سرچ مثل یه گوگل برای لاگها میمونه. میتونی میلیونها خط لاگ رو تو چند ثانیه سرچ کنی.کیبانا (همون داشبورد الستیک) هم بهت یه ویو زیبا میده تا لاگها رو راحتتر بفهمی.میتونی به صورت تخصصی لاگ ها رو مدیریت کنی اون تو . برای مثال چند تا قابلیت میگم بهتون: شما میتونی لاگ هایی که تازه به انبارمون (الستیک) رسیدن رو بذاری رو دیسک های SSD و وقتی از سن لاگ هات مثلا دو ماه گذشت اینا رو کلا انتقال بدی روی دیسک های HDDت ؛ این کار باعث میشه سرچ روی لاگ های جدیدتر سریع تر باشه. یا میتونی از رو گرافانا روی لاگ هات کوئری بزنی و مانیتوریگ مشتی راه بندازی باهاش . یا حتی میتونی لاگ هات رو بین چندین سرور از کلاسترت پخش کنی تا اگه احیانا زبونم لال یه سرورت Down شد تو لاگ هات از بین نرن و همچنان در دسترس باشن و وقتی نود داون شده ت دوباره بالا اومد به صورت اتوماتیک جوین کلاستر بشه و لاگ های کلاستر رو هندل کنه و یا میتونی لاگ هات رو shard کنی و بین نود های مختلفت پخششون کنی تا زمان بازیابی دیتاهات کوتاه باشه تا حد ممکن و .... .تا الان در مورد اینکه چرا لاگ ها واسمون مهمن صحبت کردیم و هم اینکه در مورد اینکه چرا جایی که لاگ هارو نگهداری میکنیم هم مهمه صحبت کردیم. حالا بیاییم در این مورد صحبت کنیم که چطور میشه لاگ هارو فرستاد به انبار داده مون؟ برای این کار یه سری ابزار ها توسعه داده شده . تعدادشون هم به نسبت زیاده حتی. مثلا Filebeat , Fluentbit و Vector .یه سری Benchmark های پابلیک در مورد این لاگ کالکتور و شیپر ها وجود داره که من لینکشو این زیر براتون میذارم که نشون میده Vector گزینه به شدت مناسبی هستش برای جاهایی که لود بالایی دارن. لینکVector بهترین عملکرد را دارد (بیش از ۲ برابر Fluent Bit در بارهای سنگین) . LPS = Log Per SecondVector کمترین مصرف را دارد (۰.۲ تا ۰.۵ برابر Fluent Bit در بارهای سنگین)Fluent Bit کمترین مصرف CPU را دارد. Vector از CPU بیشتر استفاده می‌کند اما LPS به ازای هر CPU آن مشابه Fluent Bit استخب بریم سراغ پیاده سازی سرویس هامون. اول از همه بریم فرمت لاگ های سرویس Nginx رو جوری که دوس داریم درستش کنیم . فایل nginx.conf رو باز کنید و فرمت لاگتون رو مثل کانفیگ پایینی بکنید.    log_format main escape=json
        &#039;{&#039;
            &#039;&quot;remote_addr&quot;:&quot;$remote_addr&quot;,&#039;
            &#039;&quot;time_local&quot;:&quot;$time_local&quot;,&#039;
            &#039;&quot;remote_user&quot;:&quot;$remote_user&quot;,&#039;
            &#039;&quot;request&quot;:&quot;$request&quot;,&#039;
            &#039;&quot;status&quot;: &quot;$status&quot;,&#039;
            &#039;&quot;body_bytes_sent&quot;:&quot;$body_bytes_sent&quot;,&#039;
            &#039;&quot;http_referer&quot;:&quot;$http_referer&quot;,&#039;
            &#039;&quot;http_user_agent&quot;:&quot;$http_user_agent&quot;,&#039;
            &#039;&quot;request_time&quot;:&quot;$request_time&quot;,&#039;
            &#039;&quot;request_body&quot;:&quot;$request_body&quot;,&#039;
            &#039;&quot;http_x_forwarded_for&quot;:&quot;$http_x_forwarded_for&quot;,&#039;
            &#039;&quot;http_host&quot;:&quot;$host&quot;,&#039;
            &#039;&quot;uri&quot;:&quot;$uri&quot;,&#039;
            &#039;&quot;args&quot;:&quot;$args&quot;&#039;
        &#039;}&#039;;خب الان لاگ های جدید رو چک کنیم میبینیم که تو فرمت json ذخیره میشن و ما به راحتی دیگه میتونیم اونا رو با سرویس Vectorمون بخونیم و تو الستیک ذخیره کنیم با حداقل مصرف فضای دیسک و حداقل over head .الان باید بریم سراغ نصب سرویس vector روی سرورمون . اولین کاری که میکنیم اینه که میریم به صفحه گیتهاب وکتور و بعدش برحسب نیازمون پکیجش رو دانلود میکنیم و روی سرورمون نصبش میکنیم . مثلا من سرورم دبین هستش پکیج .deb رو دانلود کردم و بعدش با استفاده از کامند زیر روی سرورم نصبش کردم .dpkg -i PACKAGE_NAME.debحالا فایل تو مسیر /etc/vector/vector.yaml کانفیگ زیر رو اضافه میکنیم بهش .sources:
  nginx_logs:
    type: file
    include:
      - /var/log/nginx/access.log
    ignore_older_secs: 600
    read_from: beginning

transforms:
  parse_nginx:
    type: remap
    inputs:
      - nginx_logs
    source: |
      parsed, _ = parse_json(.message)
      del(.message)
      ., _ = merge(., parsed)

sinks:
  elasticsearch-nginx:
    type: elasticsearch
    inputs:
      - parse_nginx
    endpoint: https://CLUSTER_IPs:9200
    auth:
      strategy: basic
      user: VECTOR_USER
      password: YOUR_PASSWORD
    tls:
      ca_file: CERT_PATH/ca.crt
      verify_certificate: false
    mode: &quot;data_stream&quot;
    data_stream:
      type: &quot;nginx&quot;
      dataset: &quot;dev&quot;
      namespace: &quot;default&quot;
    bulk:
      action: &quot;create&quot;
    batch:
      max_bytes: 1
      max_events: 1
      timeout_secs: 1
خب بیایین یکمی در مورد کانفیگ بالایی صحبت کنیم . ببینید در کل هر پایپلاینی که برای لاگ ها میزنید کلا سه بخش اصلی داره. یه بخشش برای این هستش که شما لاگ ها دریافت کنید یا بخونید از فایلی . مرحله بعدیش میتونید یه سری تمیز کاری ها یا فیلتر ها انجام بدید روش و در مرحله نهایی باید مکان نهایی برای ذخیره لاگ ها رو بدید بهش. اینجا ما اومدیم گفتیم برو از مسیر پیش فرض لاگ های انجین ایکس لاگ هات رو بخون بعد بیار پارسش کن و فیلد هاش رو جدا کن از هم و بعد اون دیتای گنده قبل از پارس شدن دیتا رو پاک کن تا لاگ هامون جای اضافی نگیرن رو دیسک الستیکمون و در نهایت بیار و بریزش تو الستیک مون .خب اینجا چند تا نکته هستش تو بخش سینک کردن دیتا تو الستیک:مورد اول اینکه برای هندل کردن دیتا های حجیم شما میتونید از مفاهیم Data stream یا Alias ها در الستیک استفاده کنید. به این صورت که شما اون جلو یه آبجکتی دارید با یه نام مشخص و اون آبجکت اون پشت وصله به کلی ایندکس داخل کلاستر الستیکتون که به صورت hidden هستن. خب این از این . به علاوه مفاهیم بالاتر یه مفهوم دیگه هم داریم در الستیک به نام index lifecycle managment که همونطوری که از اسمش پیداست میاد طول عمر یه ایندکس رو مشخص میکنه و طبق فازبندی هایی میاد اونا رو منتقل میکنه به فاز های بعدی و اگر دوست داشته باشید بعد از مدتی کلا پاکش میکنه . خب این باعث میشه شما لاگ های 10 سال پیشتون رو بتونید پاک کنید اگر نیاز نباشه. یا اگر نیازه ولی کم استفاده میشه انتقالش بدید به سرور هایی با دیسک های کم ارزش تر با سرعت پایین تر تا پرفورمنس کلی کلاستر هاتون به مشکل نخوره. اینم از این. خب بریم سمت الستیکمون کارای دیتا استریم و index template رو هم اون ور اوکی کنیم به عنوان حسن خطام مسئله.شما میتونید دستورات خودتون رو به کلاستر الستیکتون از دو روش بدید . یا مستقیم Api کلاسترمون رو میتونیم کال کنیم یا نه میتونیم از Dev Tools روی کیبانا استفاده کنیم.PUT _ilm/policy/nginx-dev
{
  &quot;policy&quot;: {
    &quot;phases&quot;: {
      &quot;hot&quot;: {
        &quot;actions&quot;: {
          &quot;rollover&quot;: {
            &quot;max_age&quot;: &quot;1d&quot;
          }
        }
      },
      &quot;delete&quot;: {
        &quot;min_age&quot;: &quot;30d&quot;,
        &quot;actions&quot;: {
          &quot;delete&quot;: {}
        }
      }
    }
  }
}خب مرحله اول میاییم یه ilm میسازیم که بگیم بهش چطور ایندکس هامون رو مدیریت کنه . مثلا این بالا من بهش گفتم یه روز اول دیتاهام تو فاز Hot باشه و اگه ایندکسی سنش 30 روز شد رو کلا پاک کن . عالی نیست؟ :)خب بریم سراغ مرحله بعدیمونPUT /_index_template/nginx-template  
{
  &quot;data_stream&quot;: {},
  &quot;index_patterns&quot;: [&quot;nginx-dev*&quot;],
  &quot;template&quot;: {
    &quot;settings&quot;: {
      &quot;index.number_of_shards&quot;: 1,
      &quot;index.number_of_replicas&quot;: &quot;0&quot;,
      &quot;index.lifecycle.name&quot;: &quot;nginx-dev&quot;
    }
  }
}این کانفیگمون هم میاد یه Template کلی برای ایندکس ها میسازه و باعث میشه هر ایندکسی که با فرمت nginx-dev-* بیاد رو میندازه پشت یه دیتااستریم و مدیریتشون میکنه.خب حالا بعد از گذشت چندین روز اگه لاگ های انجین ایکسمون رو ببینیم میبینیم که لاگ ها به صورت Hidden ذخیره شدن و اگه برید و دیتاویو ازش بسازید میتونید همونجا تو کیبانا دیتاهاتون رو به صورت لایو ببینید.این یه پیاده سازی کاملا ساده از این سرویس بود امیدوارم نفسی بیاد و بره تا تو نوشته های بعدی در مورد Best Practice های این سرویس تو محیط پروداکشن و همچنین پیاده سازیش داخل کلاستر کوبرنتیزمون بنویسم . ممنون از اینکه خوندید. عزت زیاد باد :)</description>
                <category>امیر سلطانی</category>
                <author>امیر سلطانی</author>
                <pubDate>Wed, 06 Aug 2025 15:05:25 +0330</pubDate>
            </item>
                    <item>
                <title>چطور با Jaeger یه سرویس Request Tracing راه بندازیم؟</title>
                <link>https://virgool.io/@m_59481059/%DA%86%D8%B7%D9%88%D8%B1-%D8%A8%D8%A7-jaeger-%DB%8C%D9%87-%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-request-tracing-%D8%B1%D8%A7%D9%87-%D8%A8%D9%86%D8%AF%D8%A7%D8%B2%DB%8C%D9%85-my0li2iuuvdm</link>
                <description>سلام به همه. تو این نوشته میخوام در مورد اینکه Request Tracing چیه صحبت کنیم و تو ادامه‌ش یه سرویس Jaeger راه بندازیم و Trace هارو از یه میکرو سرویس که با گولنگ نوشته شده بفرستیم به سمتش و در قدم نهایی تو Elastic search ذخیره‌ش بکنیم.خب، بیایید با این شروع کنیم که Request Tracing چیه و چرا توی سیستم‌های میکروسرویسی پیچیده بهش نیاز شدید داریم.فرض کنید یه رستوران بزرگ و شلوغ داریم. چند تا سرآشپز تو آشپزخونه دارن غذا درست می‌کنن، گارسونا مشغول سرویس دادن و سفارش گرفتن هستن، و کلی آدم دارن سفارش میدن. حالا اگه یه مشکلی پیش بیاد مثلاً یه نفر غذای اشتباهی بگیره، چطور باید بفهمیم که این اشتباه کجا اتفاق افتاده. تقصیر آشپز بوده؟ گارسون اشتباه کرده؟ یا کسی که سفارش رو گرفته؟اینجاست که مفهوم Request Tracing میاد وسط. ابزارهایی مثل Jaeger و ... دقیقا برای همین کار طراحی شدن. این ابزارها مثل یه دفترچه یادداشت به شدت دقیق کل مراحل سفارش رو یادداشت میکنن. یعنی نشون میدن که هر سفارش (یا Request) توی سیستم از کجا رد شده و چه اتفاقی براش افتاده یا حتی بهمون میگه هر شخص یا مرحله چقدر تایم مصرف کرده. اینجوری اگه یه جای کار مشکل داشته باشه یا سیستم کند بشه، می‌تونی سریع بفهمی مشکل از کجاست و درستش کنی.به نظر من، این مفهوم یکی از چیزای خیلی مهم توی راه‌اندازی و اجرای سیستم‌های میکروسرویسیه.برای راه‌اندازی Jaeger باید دو کار اولیه رو انجام بدیم:راه‌اندازی خود سرویس Jaegerپیاده سازی Jaeger داخل کد هامونبیایید در مورد خود سرویس Jaeger صحبت کنیم. سرویس Jaeger چند بخش اصلی داره، مثل Jaeger Agent, Jaeger Collector, Jaeger Query , ... . توی محیط‌های عملیاتی (Production)، بهتره که این بخش‌ها رو جداگانه اجرا کنیم. این جداگانه اجرا کردن اجزا میتونه خیلی به کنترل لود سیستم کمک کنه . ما میتونیم اجزا رو جدا از هم و در هر تعدادی که میخواییم بر روی سرور های لینوکسی خام یا کلاستر های ارکسترتورمون اجرا کنیم. حالا این اجزایی که گفتیم اسمشونو، چطور کار میکنن؟ بیایین مسیر رو یه بار از اول بریم تا انتها و توضیحش بدیم.فرض کنید درخواست میرسه به میکروسرویسی که وظیفه Insert دیتاهارو تو دیتابیس داره. کد شما طبق چیزی که شما کدشو نوشتید مدت زمانی که طول کشید این عمل Insert انجام بشه رو اندازه گیری میکنه و اینو به سمت سرویس Jaeger شما میفرسته. Jaeger Agent این داده هارو میگیره. داخل پارانتر بگم که شما میتونید این Jaeger Agent رو به صورت Side Car کنار اپ تون هم میتونه بالا بیاد. اصلا رسالت این سرویس اینه که شما درخواست هایی که داده هاش رو ذخیره کردید رو به صورت پکت های UDP بفرستید بهش. این سرویس رو TCP کار نمیکنه . اگر میخوایین با HTTP و غیره بفرستید باید مستقیم به Jaeger Collector بفرستید دیتاهاتون رو. تو قدم بعدی بخش Jaeger Collector وارد عمل میشه و دیتاها رو میگیره و یه سری کارها روش انجام میده و در نهایت یه جا باید ذخیره کنه اطلاعات رو. دو نوع روش وجود داره واسه این کار . شما میتونی دیتا رو تو خود سرویس ذخیره کنی یا بدی به یه سرویس مثل الستیک سرچ یا ... که واست دیتا هاتو نگه داره. مسلما راه کار دوم بهتره چون شما میتونید انواع روش های کلاسترینگ رو HA و FT  رو روشون پیاده سازی کنید. حالا یه شناخت کلی فراهم شد. بریم خود سرویس رو بیاریمش بالا. من تو این نوشته یه docker compose فایل ساده نوشتم که بیاره سرویس رو بالا. ولی قبلش باید یه چیز رو هم بگیم . شما میتونی تک تک این کامپوننت هارو به صورت مجزا بیاری بالا یا به صورت یکجا. روش اول برای محیط پروداکشن توصیه میشه و روش دوم برای محیط تست بیشتر. ما تو این نوشته از روش دوم استفاده خواهیم کرد.البته یه نوع معماری دیگه هم وجود داره که میان و یه چیزی مثل Kafka هم میارن وسط که اونم واقعا فوق العاده‌س . تو نوشته های بعدی در مورد اینکه چرا چیزی مثل کانفکا رو اصلا بازی میدیم هم صحبت میکنیم.فایل داکرکامپوز رو میتونید از این لینک پیدا کنید.با دستور docker compose up -d سرویس رو اجرا میکنیم و منتظر میمونیم سرویس ها بیان بالابیایین در مورد کامپوز فایل بالایی صحبت کنیم. این کامپوز فایل سه تا سرویس داره میاره بالا. اولی خود سرویس Jaeger هست و سرویس دومی سرویس الستیک سرچ هست که برای ذخیره دیتاهامون استفاده خواهیم کرد ازش و سومی برای بصری سازی داده های داخل الستیک سرچتون هست.تو قدم بعدی نیاز داریم یه کدی بنویسیم که در شبیه سازی کنه یه میکروسرویس رو . من زبانی که برای این تست انتخاب کردم گولنگ هستش. ما تو این سناریوای که انتخاب کردیم، appa درخواست رو به appb  میفرسته و appb درخواست رو به appc میفرسته. بیایین با کد پیاده سازی کنیم.appa - main.go  . لینک کد۱ تو گیتهابappb - main.go . لینک کد۲ تو گیتهاب appc - main.go . لینک کد۳ تو گیتهاب کد هارو بردارید و کامپایلشون کنید یا از بخش Release ها فایل آماده شو بردارید و ران کنید و دستور curl http://SERVERIP_URL:8080 رو بزنید.الان میتونید ببینید تریس هامون دارن میان و تو الستیک سرچمون میشیننهمچنین میتونیم تو خود UI سرویس Jaeger تریس هارو به صورت خیلی خوشگل ببینیم . بر روی پورت 16686 میتونید این صفحه رو ببینید.خب الان همونطوری که میبینید ما اومدیم به صورت میکروسرویس سه تا سرویس رو به صورت جداگانه آوردیم بالا. هر کدوم از این سرویس یه تایم رندومی رو مصرف میکنه و ریکوئست رو میفرسته به میکرو سرویس بعدی.یه نکته کنکوری و خیلی مهم . هر کدوم از این میکروسرویس ها به صورت جداگانه تریس هارو میفرستن به سمت سرویس Jaeger . الان سرویس ما چطور میفهمه چی به چیه و ترتیب ها چطورن؟ اینجاست که کم کم دارید وارد دنیای شاهکار Jaeger میشید. بیایین یکمی موضوع رو بازش کنیمفرض میکنیم ما درخواستی رو به میکروسرویس اولی میزنیم . اون یه Tracer  واسه خودش و به نام سرویس خودش ایجاد میکنه و یه TraceID و یه SpanID جنریت میکنه واسه خودش . بعد یه کاری رو انجام میده (مثلا تو دیتابیس یه چیزی رو مینویسه) بعدش مدت زمانی که این فرآیند زمان برد رو ذخیره میکنه تو مغزش و زمانی که درخواست رو میخواد بده به میکروسرویس بعدی تو هدر های درخواستش مینویسه که ParentSpanID ایت میکروسرویس اولی هستش و TraceID رو هم بهش میده تا ما بدونیم این ادامه همونه. و این سلسله اتفاقات میافتن پشت سر هم. همه میکروسرویس ها اطلاعات تریس هاشون رو به صورت مجزی میفرستن و سرویس Jaeger اون ور با استفاده از TraceID و ParentSpanID میتونه سلسله مراتب رو تشخیص بده . این یه شاهکاره واقعا به نظرم. در نهایت هر درخواست ورودی براش همچین درختی درست میشه و میفهمه موارد مختلف رو. تو نوشته های بعدی سعی میکنم در مورد Best Practice های این سرویس تو محیط پروداکشن بنویسم . مرسی از اینکه خوندید . عزت زیاد :)</description>
                <category>امیر سلطانی</category>
                <author>امیر سلطانی</author>
                <pubDate>Wed, 12 Feb 2025 14:42:36 +0330</pubDate>
            </item>
                    <item>
                <title>چطور DHCP سرور دست ساز درست کنیم؟</title>
                <link>https://virgool.io/@m_59481059/%DA%86%D8%B7%D9%88%D8%B1-dhcp-%D8%B3%D8%B1%D9%88%D8%B1-%D8%AF%D8%B3%D8%AA-%D8%B3%D8%A7%D8%B2-%D8%AF%D8%B1%D8%B3%D8%AA-%DA%A9%D9%86%DB%8C%D9%85-zwvjksexdwy6</link>
                <description>تو این نوشته میخوام در مورد این بنویسم شما چطور میتونید یه DHCP سرور راه بندازید. تو این سناریو ما یه سرور DHCP سرور راه میندازیم که به کلاینت هاش مقدار IP میده و بهشون assign میکنه اون آی پی رو. خب همین اول کار بگم که این نوشته نمیخواد در مورد این صحبت کنه که مفاهیم چی هستن وصرفا پیاده سازی میپردازه و اگه نمیدونید DHCP رو چرا ازش استفاده میکنن بهتره برید بخونید در موردش تو مرحله اول.اول باید 4 تا مرحله اصلی assign کردن یه آی پی به یه سخت افزار رو برسی کنیم. مراحل به ترتیب این زیر مینویسمشون: DHCP Discover : تو این مرحله سخت افزاری که به یه شبکه جدید اضافه شد میاد و یه ریکوئست برادکست میکنه به شبکه تا بفهمه کیه سرور دی اچ سی پیDHCP Offer : سرور دی اچ سی پی یه آی پی رو در نظر میگیره و تو شبکه برادکست میکنهDHCP Request : کلاینت درخواست رزور آی پی را به سرور دی اچ سی پی ارسال میکندDHCP Pack: دی اچ سی پی سرور به کلاینت درخواست  میفرسته و میگه که من آی پی رو برات رزرو کردم. برو حالشو ببر :)خب بریم سراغ پیاده سازی DHCP Server . اول از همه روی سرور دستور زیر رو میزنیم :yum install dhcpخروجی باید یه چیزی تو مایه های عکس پایینی باشه.بعد از نصبش باید اقدام کنیم به کانفیگش.  فایلش رو باز میکنیم و میریم تو کارش:vim /etc/dhcp/dhcpd.confو فایلش در نهایت باید اینطوری بشه :خب خط به خط بررسی کنیم کانفیگی که زدیم واسش رو . خط اول مشخص میکنه که subnet مون چیه و netmask مون چیه و میگه برای این سابنت و نت مسک بیا کانفیگ زیر رو اعمال کن. تو خط دوم میگیم که یه آی پی بده بهش از رنج 10.10.1.200 تا 10.10.1.240 .در خط بعدی بهش میگیم که آی پی router یا به قول  خودمون Gateway مون چنده. این آی پی برای ارتباط با سایر نتورک هایی که خارج از subnet هستن تعریف میشن.تو خط بعدی  یه مفهوم خیلی مهم تعریف شده است . بیایین یکمی مفهوم broadcasting رو توضیح بدم بهتون.بیایین یکمی اساسی تر بررسی کنیم داستانو. وقتی شما میخوایید یه آی پی رو پینگ کنید چه اتفاقی پشت پرده میوفته؟ واقعیت اینه که مهم ترین چیز اون آی پی نیست .بلکه اون مک آدرسه است. در کل ببینید تو شبکه مهم ترین چیز اون مک آدرسه هست نه آی پی. فرض کنید من میخوام آی پی 10.10.1.250 رو پینگ کنم یا بهش وصل شم. ما در حقیقت از اون آی پی برای پیدا کردن و رسیدن به مک آدرس سخت افزار مقصد استفاده میکنیم(آی پی لایه سه ای است و مک آدرس لایه دو ای).برای اینکه بفهمیم مک آدرس مربوط به اون آی پی چیه باید چیکار کنیم؟ باید به کل سیستم های عضو شبکه پیام بفرستیم و از هر کدوم جواب بگیریم و تا در نهایت بفهمیم مک آدرس این آی پی چیه. خب برای این کار یه پکت میسازیم و تو قسمت source ip آی پی خود سیستمی که میخواد پینگ کنه یه چیز دیگه رو قرارش میده . تو قسمت src mac آدرس مک سخت افزاری سیستم مبدا رو میزنیم (12 تا کاراکتره که دو تا دوتا تقسیم میشه یا سه تا سه تا . بستگی داره اون شرکتی ای که اون سخت افزار رو ساخته. ). برای پر کردن قسمت dst ip دو تا گزینه داریم:راه حل اول اینه که به دونه دونه سیستم های عضو شبکه پکت ارسال کنیم به صورت جداگانه و اونا با دیدن دوازده تا F ای که تو پکته هست بفهمن که ما داریم دنبال یکی میگردیم و آی پی و مک آدرس هاشونو برگردونن بهمون.راه حل دوم اینه که آدرس برادکست رو تو پکت بذاریم و بفرستیم بره. با این کار به تموم سیستم های عضو نتورک پکت ارسال میشه و اونا با دیدن دوازده تا F به ما جواب رو آی پی و مک آدرسشون رو برمیگردونن.خب حالا فهمیدید برادکست چیکار میکنه پشت پرده و چقدر کارمون رو راحت میکنه. مورد های بعدی هم برای میزان تایمی که آی پی رزرو بمونه برای یه سخت افزار کانفیگ میکنه.بعدش میریم و سرویس رو استارت میکنیم و استارتش میکنیم و بعد status ش رو میگیریم ببینیم اومده بالا یا نه.فقط یه نکته ای که هست اینه که اون آدرس نتورکی که میدید رو باید حداقل روی یکی از interface  های موجود رو سرورتون قابل route دهی باشه. به طور مثال سرورتون دارای آی پی 10.10.1.16 با netmask 255.255.255.0 , در این حالت شما میتونید برای مثال رنج آی پی 10.10.1.100 الی 10.10.1.150 رو به کلاینت هاتون بدید. خب تو مرحله قبلی اگه استارت موفقیت آمیز نبود دستور زیر رو بزنید و لاگ بخونید تا متوجه مشکل بشید . خیلی احتمالش بالاست که مشکل از خطای سینتکسی باشه یا خطای عدم همخوانی آدرس نتورکتون با آدرس اینترفیس هاتون.journalctl -xeخب الان همه چی سمت سرور اوکی شد. بریم سمت کلاینت یه کاریش بکنیم که بره از سرور DHCP مون آی پی بگیره. تنها کار اینه که تو قسمت کانفیگ های سیستم عامل کلاینت به اینترفیس این کانفیگ رو بدیم که هر موقع نیاز بود آی پی بگیره بره از سرور DHCP آی پی بگیره. تو قسمت onboot هم بهش میگیم که اگه سرور ریست شد اینترفیس بیاد بالا به صورت اتوماتیک.کانفیگ رو از مسیر زیر باز کنید و مثل قسمت پایین ترش کانفیگش کنید:/etc/sysconfig/network-scripts/ifcfg-eth0DEVICE=eth0
BOOTPROTO=dhcp
TYPE=Ethernet
ONBOOT=yesخب بعدش میتونید با دستور ifconfig INTERFACE _NAME  آی پی این کلاینت رو چک کنیم . و بعد نتورک سرور کلاینت رو ریستارت کنیم تا بره از سرور DHCP آی پی جدید بگیره. برای این کار دستور زیر رو میزنیم:و الان باید با اجرای دستور ifconfig INTERFACE_NAME میبینیم که آدرس آی پی جدید مطابق با Range ای که تو کانفیگ های سرور DHCP داده بودیم به سرورمون Assign شده است.حالا میریم تو سرور DHCP  و میریم به مسیر زیر تا ببینیم آی پی هایی که Assign شدن به سخت افزار ها کدوما هستن.همونطور که میبینید به مک آدرس fa:16:3e....  مقدار آی پی 10.10.1.200 Assign شده و همه چی عین گل و بلبل سر جای خودش کار میکنه. تا درودی دیگر بدرود ؛)</description>
                <category>امیر سلطانی</category>
                <author>امیر سلطانی</author>
                <pubDate>Mon, 05 Feb 2024 16:31:42 +0330</pubDate>
            </item>
                    <item>
                <title>چطور یه DNS Master Slaveسرور با قابلیت Caching راه بیندازیم؟</title>
                <link>https://virgool.io/@m_59481059/how-config-a-mster-slave-dns-server-ny2abils6hd7</link>
                <description>تو این نوشته میخوایم در مورد اینکه چطور میتونیم یه DNS سرور داشته باشیم صحبت کنیم. سناریوای که میخواییم پیاده سازیش کنیم از این قراره که یه دی ان اس سرور مستر داریم که این سرور به اینترنت دسترسی داره و میتونه همه چیو از اینترنت Resolve کنه. در کنار این سرور یه DNS سرور اسلیو هم داریم که به اینترنت دسترسی نداره و ازش برای کم کردن لود روی سرور اصلی استفاده خواهیم کرد و یه سرور دیگه هم داریم که مثل یه کلاینت ساده س که به عنوان مثال میخواد Google.com رو ریزالو کنه.راستی کلاینت هم اینترنت نداره و فقط به دی ان اس سرور اسلیو دسترسی شبکه ای داره.Master DNS : 192.168.1.172Slave DNS : 192.168.1.102Test Clientخب تو اولین مرحله سرور مستر رو روش DNSرو پیاده سازی میکنیم:بعد از نصب پکیج های مورد نیاز، باید کانفیگشون کنیم. با ادیتور vim فایل کانفیگشو باز میکنیم.(با غیر vim باز کنید حلالتون نمیکنم :) ) . vim /etc/named.conf کانفیگتون باید شبیه عکس بالایی بشه. تو کانفیگ هاش خط های زیر تغییر کردن.listen-on port 53 { 127.0.0.1;  any; };
allow-query  { localhost; any; };
dnssec-enable no;
dnssec-validation no; تو اولین خط به دی ان اس سرورمون میگیم که روی هر آی پی ای که سیستم داره روی پورت 53 به درخواست هایی میاد گوش بده و بهشون جواب بده. وقتی یه کلاینت میخواد مثلا Google.com رو  Reslove کنه به دی ان اس سرور ما query میزنه و میپرسه . خط دوم میگه که چه کلاینت هایی با چه رنج آی پی ای میتونن کوئری بزنن رو دی ان اس سرور ما.خط سوم و چهارم برای امضای ریسپانس هایی که سرور به کلاینت برمیگردونه استفاده میشه و ما برای این آموزش نیازی به اینا و روبه رو شدن با چالش هاش نداریم پس غیرفعالشون میکنیم.قدم بعدی اینه که سرویس رو استارت کنیم و تستش کنیم.سرویس استارت شد و Enable هم شد . حالا میریم که تستش کنیم. برای تست فایل /etc/resolve.conf رو باز میکنیم و آی پی سرور مستر(192.168.1.172) رو جلوی nameserver مینویسیم و بعدش مثل عکس پایینی تستش میکنیم که اوکیه یا خیر.همانطور که بالاتر میبینید آدرس گوگل کامل ریزالو میشه و سروری که این کار رو انجام داده سروری با آی پی 192.168.1.172 ئه(سرور مسترمونه- اون پایین پایینا نوشته این آی پی رو).پس مسترمون درست کار میکنه . الان میریم سراغ سرور اسلیو که کانفیگش کنیم. اول از همه bind و bind-utils رو روش نصب میکنیم و میریم تا کانفیگش کنیم مثل عکس پایینی.تغییراتی که دادیم ایناست:listen-on port 53 { 127.0.0.1;  any; };
allow-query  { localhost; any; };
forwarders { 192.168.1.172; };
dnssec-enable no;
dnssec-validation no;خط سوم به دی ان اس سرور اسلیو ، دی ان اس سرور مستر رو معرفی میکنه. وقتی کلاینتی چیزی از سرور اسلیو بپرسه ؛ اگه اون جوابشو بدونه برمیگردونه وگرنه فورواردش میکنه به دی ان اس مستر و از اون میپرسه.حالا تقریبا تموم شده همه چی . بریم یه ماشین تستی بیاریم بالا و وصلش کنیم به دی ان اس سرور اسلیو ببینیم همه چی اوکیه یا خیر (مگه دست خودشه اوکی نباشه؟ :) ).رو سرور کلاینت تستی فایل /etc/resolve.conf رو باز میکنین و تغییرش میدید به دی ان اس سرور اسلیومون(192.168.1.102).مثل عکس زیری باید باشه.و بعد :همونطور که میبینید همه چی ردیفه . حالا بیایید یکم ور بریم باهاش و ببینیم این cache کردن ها دقیقا چطور کار میکنن.ما اومدیم رو سرور کلاینت تستی مون یه آدرس رو ریزالو کردیم و مبینید که در عرض 0 میلی ثانیه جواب داده به کوئری‌مون. خب این نشون میده که سیستم کش کردنمون درست کار میکنه. حالا یه سوال جدید. بیایین کش دی ان اس سرور مسترمون رو پاک کنیم به کل .ببینیم نتیجه رو کلاینت چطوریه.با دستور بالایی میتونید کش دی ان اس تون رو پاک کنید. بعدش دوباره میریم رو کلاینت و همون کوئری قبلی رو اجرا میکنیم.دوباره 0 میلی ثانیه. پس این نشون میده که دی ان اس سرور اسلیو درست داره به کار کش کردنش عمل میکنه و هر چیزی رو نمیفرسته سمت مستره. حالا بیایین کش اسلیو رو هم پاک کنیم ببینیم نتیجه چی میشه.و بعد روی کلاینت اجرای کوئری قبلی برای ریزالو یک آدرس url .نتیجه رو میبینید که در عرض 1144 میلی ثانیه برمیگردونه. به عبارتی کلاینت از اسلیو پرسید و وقتی دید جوابی نداره اسلیوه، اسلیو میره از مستر میپرسه و وقتی میبینه اونم جوابی نداره (تو cache جوابی نداره ) میره از دی ان اس سرور های سطح اینترنت میپرسه و جواب رو برمیگردونه و این میشه که طول میکشه.حالا من یه تست دیگه کردم و یادم رفت اسکرین شات بگیرم . اونم این بود که رو اسلیو فلاش بزنیم ولی تو کش مستر داشته باشیم جواب رو. وقتی این کارو میکردیم کوئری در عرض 34 میلی ثانیه جواب داده میشد.خودم قصد دارم تو نوشته بعدی یا یکی از نوشته های بعدیم در مورد ریکورد های DNS و Zone اینا بنویسم تو DNS و توضیح بدمشون. ایشالا تو اولین فرصتامیدوارم مفید بوده باشه نوشته‌ام. تا درودی دیگر بدرود :) </description>
                <category>امیر سلطانی</category>
                <author>امیر سلطانی</author>
                <pubDate>Tue, 30 Jan 2024 12:03:39 +0330</pubDate>
            </item>
            </channel>
</rss>