درک رویه‌های رمزنگاری و برقراری ارتباط در SSH

SSH و یا Secure Shell، یک پروتکل امن ارتباطی است و به عنوان ایمن‌ترین روش برای مدیریت سرور از راه دور شناخته می‌شود. این پروتکل با بهره‌گیری از چند تکنولوژی رمزگذاری، روش‌هایی را برای پیاده‌سازی ارتباط ایمن رمزنگاری شده بین کلاینت و سرور، احراز هویت هر یک از طرفین و اجرای دستورات و نمایش نتایج آن ارائه می‌دهد.

در این راهنما، به تکنیک‌های رمزنگاری استفاده شده در لایه‌های SSH و روش‌هایی که این پروتکل برای برقراری ارتباطی امن مورد استفاده قرار می‌دهد، خواهیم پرداخت. اطلاعات موجود در این مقاله، می‌تواند دید کلی خوبی از گام‌های مختلف مورد نیاز برای تشکیل یک ارتباط امن و احراز هویت شده را ارائه نماید.

رمزنگاری متقارن، رمزنگاری نامتقارن، و درهم‌سازی!

برای انتقال امن داده‌ها، SSH از چند تکنیک متعدد برای تغییر داده در مراحل مختلف استفاده می‌کند. این تکنیک‌ها مبتنی بر رمزنگاری متقارن، نامتقارن و البته درهم‌سازی هستند.

رمزنگاری متقارن

نحوه‌ی ارتباط بین بخش‌هایی که عمل رمزگذاری و رمزگشایی داده‌ای را انجام می‌دهند، مشخص‌کننده‌ی آن است که آیا یک رمزنگاری متقارن است و یا نامتقارن.

رمزنگاری متقارن روشی است که در آن یک کلید برای رمزنگاری و بازگشایی آن مورد استفاده قرار می‌گیرد. این بدین معنی است که هر فردی که این تنها کلید را در اختیار داشته باشد، می‌تواند داده‌ها را رمزگذاری و یا رمزگشایی کند.

این شیوه‌ی رمزنگاری اغلب رمزگذاریِ “محرمانه‌ی مشترک – shared secret”، و یا “کلید محرمانه – secret key” نامیده می‌شود. در این روش تنها یک کلید برای تمامی امور رمزگذاری و رمزگشایی مورد استفاده قرار می‌گیرد، و یا در حالاتی جفت کلیدی وجود دارد که به راحتی می‌توان به مرتبط بودن‌شان پی برد و به دست آوردن کلید متقابل از یکی از کلیدها بدیهی باشد.

SSH از کلید متقارن برای رمزگذاری کل ارتباط استفاده می‌کند. بر خلاف آنچه ممکن است برخی گمان کنند، از جفت کلیدهای عمومی – خصوصی رمزنگاری نامتقارن تنها برای مرحله‌ی راستی‌آزماییِ تشخیص هویت کاربر بهره گرفته می‌شود، و از این روش برای رمزگذاری ارتباط مورد استفاده قرار نمی‌گیرد. از طرفی دیگر احراز هویت SSH از طریق وارد کردن رمز ورودی نیز از طریق این رمزنگاری متقارن، امن می‌گردد.

در ایجاد کلید متقارن، هم سرور و هم کلاینت نقش ایفا می‌کنند، بدون آنکه نتیجه‌ی نهایی برای طرف‌های خارج از این ارتباط نمایان گردد. این کلید محرمانه در روشی که به آن الگوریتم تبادل کلید شهرت یافته، ساخته می‌شود. این الگوریتمِ تبادل منجر به ایجاد یک کلیدِ واحدِ همسان، مستقلا توسط هر کدام یک از طرفین ارتباط، سرور و کلاینت، می‌گردد. این کلید از طریق اشتراک‌گذاری داده‌هایی عمومی و تغییر آن با برخی داده‌های محرمانه ساخته می‌شود که جزئیات بیشتر آن را در بخش‌های آتی به تفصیل ارائه خواهیم داد.

کلید رمزنگاری متقارن ساخته شده از این روش، از نوع session-based است و وظیفه‌ی رمزگذاری داده‌ی دریافتی – ارسالی بین کلاینت و سرور را دارد. هنگامی که این رمز کلید ایجاد می‌گردد، تمامی داده‌های انتقالی پس از آن بایستی با همین کلید محرمانه‌ی اشتراکی رمزگذاری شود. دقت کنید که ایجاد کلید محرمانه و رمزگذاری کل کانال ارتباطی، پیش از انجام احراز هویت کلاینت صورت می‌گیرد.

SSH می‌تواند از روش‌های متنوعی برای رمزنگاری متقارن خود استفاده کند؛ AES ،Blowfish ،3DES ،CAST128 و Arcfour. در انتخاب روش رمزنگاری، هم سرور و هم کلاینت می‌توانند نقش ایفا کنند و بر اساس ترتیب اولویت در نظر گرفته شده‌ی‌شان، به توافق برسند. در واقع اولین گزینه از لیست روش‌های رمزنگاری مورد پشتیبانی کلاینت که مورد قبول سرور هم باشد، مورد استفاده قرار می‌گیرد.

رمزنگاری نامتقارن

رمزنگاری نامتقارن از این جهت با نوع متقارن آن متفاوت است که برای ارسال داده در یک جهت، به دو کلید مرتبط مورد نیاز است. یکی از این کلیدها، کلید خصوصی نام دارد، و دیگری کلید عمومی.

کلید عمومی می‌تواند آزادانه انتشار یابد و در اختیار هر کاربری قرار گیرد. این کلید یک جفت خصوصی هم دارد که به طور ریاضی با هم مرتبط‌اند، اما عملا نمی‌توان با داشتن کلید عمومی، به کلید خصوصی آن رسید. ارتباط ریاضی بین این دو کلید، امکان رمزگذاری داده‌ها از طریق کلید عمومی، و رمزگشایی آن تنها از طریق کلید خصوصی را فراهم می‌کند. اما اینکه گفته می‌شود این مسیر تنها یک طرفه است، به چه معنی است؟ به این معنی است که کلید عمومی توانایی رمزگشایی از داده‌ای که خود رمزگذاری کرده را ندارد. حتی رمزگشایی از داده‌ای که از طریق جفت کلید خصوصی آن رمزگذاری شده برای آن امکان‌پذیر نیست.

تا به اینجا باید اهمیت فراوان کلید خصوصی برای‌تان مشخص شده باشد. تحت هیچ شرایطی این کلید نباید با دیگران به اشتراک گذاشته شود. امن نگه داشتن این کلید، لازمه‌ی برقرار داشتن اعتبار الگوی کلید عمومی – خصوصی و در نتیجه‌ی آن، نفع بردن از قابلیت رمزگذاری و احراز هویت آن است. کلید خصوصی تنها بخشی از این الگو است که امکان رمزگشایی از داده‌های رمزگذاری شده‌ توسط ‌جفت کلید عمومی خود را فراهم می‌کند. به بیان دیگر، هر کلاینتی که توانایی رمزگشایی صحیح از داده‌ای را ابراز کند، نشان داده است که کلید خصوصی آن در اختیار وی است.

SSH از رمزنگاری نامتقارن در گام‌های مختلفی بهره می‌گیرد. یکی از آن موارد، در ابتدای روند کلید تبادل برای ایجاد رمزنگاری متقارن و رمزگذاری session است. در این مرحله، هر دو عامل ارتباطی، کلاینت و سرور، یک جفت کلید موقتی ایجاد و کلید عمومی آن را برای یک‌دیگر ارسال می‌کنند تا در ساخت کلید محرمانه‌ی اشتراکیِ – shared secret مورد نیاز در رمزنگاری متقارن استفاده گردد.

در کاربردی دیگر، SSH از رمزنگاری نامتقارن برای احراز هویت کلاینت برای سرور استفاده می‌کند. در این حالت، کلاینت یک جفت کلید ایجاد می‌کند و کلید عمومی آن را در هر سروری که بخواهد به آن دسترسی داشته باشد، آپلود می‌کند. مکان قرارگیری این کلید عمومی در سرور، پوشه‌ای به نام authorized_keys در مسیر ~/.ssh است. شاید ذکر این نکته در همین‌جا خالی از لطف نباشد که بگوییم پوشه‌ی authorized_keys را با پوشه‌ی known_hosts در همین مسیر اما در سیستم کلاینت اشتباه نگیرید. پوشه‌ی known_hosts حاوی کلیدهای عمومی از سرورهای مورد اعتماد کلاینت است. به عبارت دیگر، از طریق آن کلاینت می‌تواند اعتبار هویت ادعایی یک سرور را راستی‌آزمایی کند.

پس از آنکه رمزنگاری متقارن به منظور ایمن‌سازی کل ارتباط بین کلاینت و سرور ایجاد گردید، حال وقت آن رسیده است که کلاینت هویت خود را برای سرور احراز کند. در این گام، سرور می‌تواند با استفاده از کلید عمومی موجود در پوشه‌ی authorized_keys، چالش رمزنگاری را برای کلاینتِ درخواست‌کننده ایجاد نماید. اگر کلاینت بتواند ثابت کند که توانایی رمزگشایی داده‌ی رمزگذاری شده‌ی مورد نظر سرور را دارد، به این معنی است که کلید خصوصی متناظر آن کلید عمومی در اختیار اوست و سرور می‌تواند اجازه‌ی دسترسی را برای کلاینت فراهم نماید.

درهم‌سازی

شکل دیگری از تغییر در داده‌ای که SSH از آن بهره می‌گیرد، درهم‌سازی رمزنگارانه است. توابع درهم‌سازی رمزنگارانه، روش‌هایی برای ایجاد «امضای فشرده‌» و یا «خلاصه‌ای از مجموعه‌ای از داده‌ها» هستند. مهم‌ترین ویژگی متمایز آن‌ها یک طرفه بودن عملیات آن‌ها است. به این معنی که تقریبا امکان رسیدن به داده‌ی اولیه، از طریق داده‌ی درهم‌سازی شده وجود ندارد و می‌توان روی منحصر به فرد بودن خروجی‌ها اطمینان داشت.

هر بار استفاده از یک داده‌ی مشخص در یک تابع درهم‌ساز به‌خصوص، بایستی نتیجه‌ی یکسانی داشته باشد. بنابراین اگر کوچک‌ترین تغییری در داده‌ی ورودی اعمال شود، خروجی درهم‌ساز نیز باید نتیجه‌ی متفاوتی ارائه دهد. از طرف دیگر، کاربر نمی‌تواند از طریق دسترسی به خروجی درهم‌سازی شده، به داده‌ی اصلی برسد، اما باید بتواند آن خروجی را با توجه به داده‌ی اصلی، راستی‌آزمایی کند.

با توجه به مواردی که گفته شد، از درهم‌سازی عمدتا در روش‌های تشخیص یکپارچگی داده‌ها و صحت ارتباط مورد استفاده قرار می‌گیرد. اصلی‌ترین استفاده از این روش در SSH، توسط HMAC – Hash-based Message Authentication Code، و یا کد اصالت‌سنجی پیام بر پایه‌ی درهم‌سازی است. این مکانیزم به این دلیل مورد استفاده قرار می‌گیرد که اطمینان حاصل شود داده‌ی دریافتی بدون هیچ‌گونه تغییر و دخل و تصرفی از فرستنده به گیرنده رسیده است.

همان‌طور که پیش‌تر کلیت شکل‌گیری ارتباط رمزنگاری متقارن را بررسی کردیم، برای صحت‌سنجی داده‌های دریافتی – ارسالی، یکی از الگوریتم‌های “کد اصالت‌سنجی پیام – MAC” مورد استفاده قرار می‌گیرد. در این روش نیز اولین الگوریتمی که سرور و کلاینت مشترکا از آن پشتیبانی می‌کنند، به‌کار گرفته خواهد شد.

هر داده‌ای که پس از ایجاد کانال ارتباطی رمزگذاری شده تبادل می‌شود، بایستی حاوی کد اصالت‌سنجی پیام باشد تا هر دو سمت ارتباط بتوانند صحت و یکپارچگی داده‌های دریافت – ارسالی را تایید کنند. این را هم بگوییم که کد اصالت‌سنجی پیام، از ترکیب کلید محرمانه‌ی اشتراکی متقارن، شماره‌ی توالی بسته‌ی داده‌ی ارسالی، و خوده داده‌ی اصلی محاسبه می‌گردد.

ذکر این نکته نیز ضروری است که در روش به کار رفته در پروتکل SSH، “کد اصالت‌سنجی پیام – MAC”، ابتدا در حالت cleartext محاسبه، سپس داده‌ی اصلی رمزگذاری و در نهایت کد اصالت‌سنجی پیام محاسبه شده به انتهای داده‌ی رمزگذاری شده پیوست می‌گردد. اما محققین امنیتی توصیه می‌کنند ابتدا کل داده رمگذاری شود و سپس از داده‌ی رمز‌گذاری شده اقدام به تهیه‌ی MAC گردد.

SSH چگونه کار می‌کند؟

احتمالا تا به این جای کار درک بنیادی از چگونگی عملکرد SSH پیدا کرده‌اید. پروتکل SSH از مدل کلاینت – سروری برای احراز هویت دو طرف ارتباط و رمزگذاری داده‌های ارسالی استفاده می‌کند.

سرور وظیفه دارد همواره به پورت‌های در نظر گرفته شده گوش دهد. در هنگام رسیدن درخواست، سرور ابتدا ایمن‌سازی ارتباط را انجام می‌دهد و سپس در صورت تایید احراز هویت کاربر، محیط کاربری مبتنی بر سطح دسترسی وی را فراهم می‌نماید. 

کلاینت نیز موظف به آغاز  TCP handshake اولیه با سرور، آغاز ایجاد ارتباطی امن، صحت‌سنجی هویت سرور با اطلاعاتی که پیش‌تر از آن سرور داشته، و فراهم‌ کردن اعتبارنامه‌ای برای احراز هویت خود می‌باشد.

به طور کلی یک ارتباط SSH در دو گام جداگانه برقرار می‌گردد. نخست بایستی توافقی بین سرور و کلاینت برای تعیین نوع رمزگذاری حاصل شود و ارتباط امن ایجاد گردد. سپس بایستی هویت کاربر مورد بررسی قرار گیرد و اینکه آیا دسترسی مورد درخواست به کلاینت اهدا شود یا که خیر.

مذاکره‌ی رمزنگاری برای Session

هنگامی که ارتباط TCP از طریق کلاینت برقرار شد، سرور نسخه‌های مورد پشتیبانی خود از پروتکل‌ها را به کلاینت اعلام می‌کند. اگر کلاینت بتواند از بین پروتکل‌های پشتیبانی اعلامی، تطابقی با موارد خود پیدا کند، ارتباط ادامه پیدا می‌کند. سرور همچنین کلید عمومی خود را در اختیار می‌گذارد تا کلاینت بتواند هویت سرور مورد نظر را تصدیق کند. این کار به صورت پیش‌فرض، از طریق مقایسه‌ی کلید اعلامی با کلیدهای موجود در پوشه‌ی known_hosts در مسیر ~/.ssh صورت می‌گیرد.

در این مرحله، هر دو عضو درگیر ارتباط، ایجاد کلیدِ session را با استفاده از نسخه‌ای از الگوریتم Diffie-Hellman مورد توافق قرار می‌دهند. به این شکل که این الگوریتم، و انواع گونه‌های آن، امکان رسیدن به یک کلیدِ session محرمانه‌ی واحدی را از طریق ترکیب کلیدهای خصوصی هر یک از اعضا، به همراه داده‌ی عمومی به اشتراک گذاشته شده از سوی طرف مقابل، مستقلا برای هر یک از طرفین ارتباط فراهم می‌کند. 

از همین کلید محرمانه برای رمزنگاری کل session ارتباطی استفاده می‌شود. ذکر این نکته ضروری است که جفت کلید عمومی – خصوصی به‌کار رفته در ایجاد کلید محرمانه، کاملا جدا از کلید عمومی – خصوصی مورد استفاده در احراز هویت کلاینت برای سرور است.

بنابر آنچه گفته شد، رویه‌ی کلی و البته کلاسیک الگوریتم Diffie-Hellman به این شکل است:

۱. هر دو طرف ارتباط بر روی یک عدد اول بزرگ که به عنوان seed value مورد استفاده قرار می‌گیرد، توافق می‌کنند.

۲. هر دو طرف بر روی یک مولد رمزگذاری(عموما AES)، که برای تغییر ارقام و با روش از پیش‌تعریف شده‌ای است، توافق می‌کنند.

۳. مستقلا، هر یک از طرفین ارتباط، عدد اول دیگری تولید می‌کند که از طرف دیگر محرمانه نگاه داشته می‌شود. از این عدد به عنوان کلید خصوصی مورد استفاده برای ساخت کلید محرمانه‌ی session بهره گرفته می‌شود. (مجددا دقت کنید که این کلید خصوصی، با کلید خصوصی مورد استفاده برای مرحله‌ی احراز هویت SSH متفاوت است.)

۴. کلید خصوصی تولید شده(مرحله‌ی ۳)، به همراه مولد رمزگذاری(مرحله‌ی ۲) و عدد اول اشتراکی(مرحله‌ی ۱) به منظور ایجاد کلید عمومی مورد استفاده قرار می‌گیرد که می‌توان بدون نگرانی در اختیار طرف مقابل قرار گیرد.

۵. در این مرحله کلیدهای عمومی ایجاد شده توسط طرفین ارتباط با یکدیگر تبادل می‌گردد.

۶. هر کدام از طرفین با استفاده از کلید عمومی دریافت شده در مرحله‌ی ۵، کلید خصوصی خود، و عدد اول اشتراکی، اقدام به محاسبه‌ی کلید محرمانه‌ی اشتراکی می‌کند. اگرچه این رویه کاملا جداگانه و به صورت مستقل توسط هر یک از طرفین محاسبه می‌گردد، اما با استفاده کلیدهای عمومی و خصوصی طرف مقابل نیز، همچنان نتیجه‌ی یکسانی حاصل می‌گردد. به عبارت دیگر، هر یک از طرفین، بدون آنکه نیاز به اشتراک داده‌ای حساس از خود بر روی کانال (تا این لحظه) ناامنِ ارتباطی برای یکدیگر داشته باشند، به کلید رمزنگاری متقارن مشترکی برای ایمن‌سازی آتی کانال ارتباطی خود رسیده‌اند.

۷. کلید محرمانه‌ی اشتراکی تولید شده از این پس برای رمزگذاری کل ارتباط مورد استفاده قرار می‌گیرد.

کلید محرمانه‌ی اشتراکی که رمزگذاری کل کانال ارتباطی را بر عهده دارد، “پروتکل بسته‌ی باینری – binary packet protocol” نام دارد. ۷ گام ذکر شده‌ی فوق، امکان ایجاد کلید محرمانه‌ی اشتراکی یکسانی را توسط هر یک از طرفین، به طور کاملا مستقل فراهم می‌کند.

همان‌طور که گفته شد، کلید ایجاد شده از نوع متقارن است. به این معنی که همان کلیدی که برای رمزگذاری داده‌ها مورد استفاده قرار می‌گیرد، می‌تواند به عنوان رمزگشا نیز ایفای نقش کند. هدف از این کار این بوده است که تمام کانال ارتباطی در یک تونل رمزگذاری شده قرار گیرد و داده‌ها توسط کاربران بیرون از این چرخه‌ی ارتباط قابل رمزگشایی نباشد.

پس از ایجاد session رمزنگاری شده، حال نوبت آغاز مرحله‌ی احراز هویت است.

احراز هویت کاربر به منظور دسترسی به سرور

پیش‌تر از نظر گذراندیم که این مرحله شامل صحت‌سنجی هویت کاربر و تصمیم بر اهدای دسترسی به سرور است. بر اساس آنچه سرور از آن پشتیبانی می‌کند، روش‌های متعددی برای انجام این کار وجود دارد.

احتمالا راحت‌ترین روش استفاده از رمز باشد. در این روش کلاینت در هنگام اتصال، رمزِ حساب کاربری را به منظور دسترسی به سرور وارد می‌کند. رمز وارد شده توسط کاربر از طریق کانال رمزگذاری که پیش‌تر ایجاد شده است، برای سرور ارسال می‌گردد. بنابراین رمز وارد شده از دسترس دیگر افراد احتمالی محفوظ می‌ماند.

اگرچه رمز ارسالی از کانال رمزگذاری شده ارسال گردیده، اما به دلیل ماهیت کلی رمزها و محدود بودن پیچیدگی‌های‌شان، استفاده از آنان عموما توصیه نمی‌شود. حال آنکه رمزهای با طول متعارف و معمولی که کاربرها برای خود در نظر می‌گیرند، به راحتی با اسکریپت‌های خودکار قابل شکسته شدن هستند.

اما محبوب‌ترین و بهترین جایگزین روش استفاده از رمز، بهره‌گیری از جفت کلید SSH است. جفت کلید SSH از نوع نامتقارن هستند. به این معنی که هر کدام از این دو کلید مرتبط، کارایی متفاوتی دارند.

در این حالت، کلید عمومی برای رمزگذاری داده، و کلید خصوصی به منظور رمزگشایی مورد استفاده قرار می‌گیرد. کلید عمومی به طور آزادانه امکان اشتراک‌گذاری دارد. دلیل آن هم همان‌طور که پیش‌تر گفته شد، نبود امکان رسیدن به کلید خصوصی از طریق کلید عمومی است.

احراز هویت از طریق جفت کلید SSH، پس از ایجاد کانال رمزنگاری متقارن فراهم شده در بخش قبلی، صورت می‌گیرد. این رویه به این شکل است:

۱. کار از طریق ارسال یک ID به سرور، که آن ID منتسب به یک جفت کلیدی است که قصد داریم احراز هویت با آن صورت گیرد، آغاز می‌شود. 

۲. سرور از طریق بررسی فایل‌های موجود در پوشه‌ی authorized_keys خود، وجود کلیدی با ID ادعا شده توسط کلاینت را مورد بررسی قرار می‌دهد.

۳. اگر کلید عمومی با ID مورد نظر در این فایل‌ها وجود داشت، سرور عدد تصادفی ساخته و با استفاده از کلید عمومی یافت شده، اقدام به رمزگذاری عدد تصادفی می‌کند.

۴. سرور خروجی عدد تصادفی رمزگذاری شده‌ی مرحله‌ی قبل را به کلاینت می‌فرستد.

۵. اگر کلاینت واقعا کلید خصوصیِ کلید عمومی مورد نظر را در اختیار داشته باشد، باید بتواند داده‌ی ارسالی از سمت سرور را رمزگشایی و عدد تصادفی سرور را بازگو نماید.

۶. کلاینت عدد رمزگشایی شده را با کلید محرمانه‌ی اشتراکی که برای رمزگذاری کل کانال ارتباطی مورد استفاده قرار گرفته، ترکیب می‌کند. سپس اقدام به محاسبه‌ی درهم‌ساز MD5 این ترکیب می‌نماید.

۷. کلاینت حاصل این درهم‌ساز MD5 را به سرور، به عنوان جواب عدد ارسالی رمزگذاری شده، ارسال می‌کند.

۸. در این مرحله، سرور نیز به نوبه‌ی خود، با استفاده از کلید محرمانه‌ی اشتراکی و عدد اصلی که برای کلاینت ارسال کرده، اقدام به محاسبه‌ی درهم‌ساز MD5 آن می‌کند. سرور مقدار به دست آمده را با مقدار دریافتی از کلاینت مقایسه کرده، و اگر برابری حاصل شد، نشان‌ دهنده‌ی آن است که کلاینت به کلید خصوصی دسترسی دارد و احراز هویت با موفقیت صورت می‌گیرد.

همان‌طور که مشاهده کردید، نامتقارنی کلیدها امکان رمزگذاری داده‌ها توسط سرور برای کلاینت را با استفاده از کلید عمومی فراهم می‌کند. کلاینت در مرحله‌ی بعد با رمزگشایی صحیح آن می‌تواند ثابت کند که کلید خصوصی در اختیارش قرار دارد. در مجموع هر کدام از روش‌های رمزنگاری مورد استفاده در این پروتکل، چه کلید اشتراکی متقارن و چه جفت کلیدهای عمومی – خصوصی نامتقارن، مزایا و امکاناتی را به این مدل ارتباطی ارائه می‌دهند.

آشنا شدن با مراحل برقراری ارتباط امن و لایه‌های رمزگذاری در هنگام استفاده از SSH می‌تواند به شما در درک بهتر اتفاقاتی که در هنگام استفاده از آن روی می‌دهد، کمک شایانی کند. خوشبختانه هم‌اکنون شما ایده‌ی بهتری نسبت به روابط بین بخش‌ها، الگوریتم‌های مختلف و چگونگی ارتباط‌شان با یکدیگر در پروتکل SSH دارید.

منابع: RFC4253 ،DigitalOcean.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *