Hootan Alghaspour
Hootan Alghaspour
خواندن ۱۲ دقیقه·۴ سال پیش

بهتر cURL کنیم

نمی شه یک ادمین لینوکسی باشید و چندساعتی برای آشنایی با هر کدام از ابزارهای خط فرمانی curl, wget, nc, grep, sed, watch, lsof, netstat, top و ... وقت نگذاشته باشید.

اگر می گوییم nc چاقوی سویسی کار با پروتکل های سطح شبکه است باید بگیم cURL شمشیر سامورایی سویسی برای دریافت/ارسال اطلاعات در سطح پروتکل های اینترنت است.

به زبان ساده cURL یک مرورگر(خط فرمانی) و کتابخانه برای انواع ارسال و دریافت اطلاعات بر بستر پروتکل های متداول و رایج اینترنت است.

با C نوشته شده و در کنفرانسی نویسنده اش (Daniel Stenberg) ذکر کرده اگر امروز هم می خواست به همین موفقیت در این نرم افزار برسد ، درنهایت دوباره از C استفاده می کرد.("...I would stick to C...")

Command line Tool & Library for transferring data using internet protocols.

cURL (pronounced 'curl') is a computer software project providing a library (libcurl) and command-line tool (curl) for transferring data using various network protocols. The name stands for "Client URL", which was first released in 1997.(wikipedia)

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

بصورت پیش فرض cURL به ساده ترین شکل ممکن عمل می کند اما در مواجه با یک کاربر حرفه ای می تواند توانایی و قابلیت جامع و قابل برنامه ریزی (ابزار و کتابخانه) برای ارتباط در بستر پروتکل های مورد پشتیبانی ارائه دهد و بیش از 230 کامندلاین آپشن دارد که بصورت مستمر در حال توسعه هستند.

به عبارت دیگر cURL فقط کاری را که به وی مشخصاً دستور داده شود انجام می دهد و کاربر براساس نیاز و انتخاب خود آپشن ها را فعال/غیرفعال می کند.

You HAVE to ask for everything to enable it!

دیدن هدر و دنبال کردن redirect

مثلاً بصورت پیش فرض Redirectها را دنبال نمی کند و فقط محتوی همان URL را می گیرد.

با آپشن i- می توان تعریف کرد هدرها را هم نمایش دهد و I- (بزرگ i) به معنای فقط نمایش هدر است.

اما اگر L- را هم اضافه کنیم آنگاه مثل حالت پیش فرض مرورگرهای معمولی redirect را هم دنبال می کند.(loop protection دارد و بعد از تعدادی ریدایرکت دیگر دنبال نمی کند.)


خواندن رنج با URL Globbing

یکی از بهترین قابلیت ها URL globbing است، یعنی می توانید یک رنج یا یک لیست را برای گرفتن به وی معرفی کنید. به همراه قابلیت ذخیره (با گزینه o- فعال می شود) ، می توان از آن برای دانلود کلیه محتوی براساس یک رنج استفاده کرد.

این قابلیت بصورت پیش فرض فعال است و با g, --globoff- غیرفعال می شود.

curl &quothttp://example.com/[1-100].png&quot //یک تا صد curl &quothttp://example.com/[001-100].png&quot // دوصفریک تا صد (سه رقمی) curl &quothttp://example.com/[0-100:2].png&quot // صفر تا صد با گام دوتایی curl &quothttp://example.com/section[a-z].html&quot // رنج حروف curl &quothttp://example.com/{one,two,three,alpha,beta}.html&quot // لیست مشخص curl &quothttp://example.com/{web,mail}-log[0-6].txt&quot // ترکیب لیست و رنج curl &quothttp://{one,two}.example.com&quot -o &quotfile_#1.txt&quot // ذخیره و خروجی روی فایل curl &quothttp://{site,host}.host[1-5].example.com&quot -o &quotsubdir/#1_#2&quot //ذخیره و خروجی با ساب دایرکتوری *Each &quotglob&quot used in a URL gets a separate variable. They are referenced as '#[num]' - that means the single letter '#' followed by the glob number which starts with 1 for the first glob and ends with the last glob.


کاری که cURL نمی کند اما wget می کند : recursive download website

برای دانلود کامل محتویات یک پوشه یا یک وب سایت از طریق http(s) یا ftp بهتره بجای اسکریپت نوشتن و اذیت کردن خودتون از wget بخوبی و سادگی استفاده کنید.

آپشنش در wget سوییچ r- یا recursive-- است.

# download website, 2 levels deep, wait 9 sec per page wget --wait=9 --recursive --level=2 http://example.org/

جهت اطلاع، برای mirror کردن هدف در wget می توانید از m- یا mirror-- استفاده کنید.

‘-m’ or ‘--mirror’ Turn on options suitable for mirroring. This option turns on recursion and time-stamping, sets infinite recursion depth and keeps FTP directory listings. It is currently equivalent to ‘-r -N -l inf --no-remove-listing’. Example: wget -m ftp://x.x.x.x/* --ftp-user=user@example.org --ftp-password=pass


روش های verbose و trace و دیدن و ذخیره جزئیات

مثل خیلی های دیگر با v- یا verbose-- توضیحات کاملتری را از فرآیندی که اتفاق می افتد می توانید ببینید. این اطلاعات اضافی با یک * در ابتدا مشخص شده اند. مثل برخی دیگر از ابزارهای لینوکسی با اضافه کردن v سطح verbosity زیاد نمی شود و همان یک v کافیست!

برای خیلی موارد بخصوص کار با پروتکل های رمزنگاری شده ممکن است verbose کافی نباشد. در این حالت می توانید از trace برای جزئیات بیشتر و ذخیره کل فرآیند در یک فایل استفاده کنید.

--trace [filename] will save a full trace in the given file name. You can also use '-' (a single minus) instead of a file name to get it passed to stdout.

اگر گزینه trace-time-- را هم استفاده کنید تایم لاین دقیقی از فرآیند خواهید دید که بخصوص در پیدا کردن گره های کند شدن ارتباط بسیار موثر است.(باید با v- بصورت همزمان استفاده شود.)

اگر از گزینه trace-ascii-- استفاده کنید، هر چیزی که ارسال و دریافت می شود را با جزئیات خیلی کامل خواهید دید یا در یک فایل ذخیره خواهید کرد. فرق آن با trace در این است که دیگر بخش hex را ذخیره نمی کند اما جزئیات کامل را ذخیره خواهد کرد.

آپشن write-out یا w-

با write-out-- می توانید اطلاعات متنوعی درباره ارتباط را پس از اتمام cURL در ترمینال ببینید.مثلاً

curl -w %{size_download} ifconfig.co

لیست variableهایی را که می توانید استفاده کنید و جزئیات بیشتر درباره این آپشن پرکاربرد را اینجا ببینید.


تعیین HTTP Headers در request

برای اینکار کافیست از گزینه H- استفاده کنید.

البته برای User-Agent گزینه A, --user-agent- نیز موجود است.

برای Referrer Page هم گزینه e, --referer- بصورت جدا هست.


ارسال اطلاعات با POST و PUT

ابزار cURL فقط برای خواندن و دریافت یکسویه اطلاعات نیست و می تواند برای ارسال اطلاعات یا فایل نیز بر بستر http, ftp, smtp,... استفاده شود.

با d- پست می کند ، با T- عمل PUT انجام می دهد، با F- می توان HTTP multipart formposts را ارسال کرد و با X- می توان برای HTTP یک custom request method تعریف کرد.

طبیعی هست که گزینه ها و شرایط آپلود متنوع و بسته به مورد هستند و زیاد است. اطلاعات بیشتر درباره آپلود و ارسال اطلاعات با cURL را اینجا ببینید.


کار با کوکی ها

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

برای خواندن و استفاده از کوکی از روی یک فایل از آپشن b- یا cookie-- و برای نوشتن کوکی ها روی یک فایل از آپشن c- یا cookie-jar-- استفاده می شود.

حالا اگر به آپشن b- یک فایل که وجود ندارد معرفی کنید، cookie engine با مقدار کوکی خالی فعال می شود و اگر وب سایت کوکی ست کند در in-memory store ذخیره می شود و اگر تعریف کرده باشید که در فایلی ذخیره شود پس از اتمام cURL روی آن نوشته خواهد شد و در آن نشست و نشست های بعد که از آن کوکی استفاده شود معتبر است. معمولاً برای کار با وب سایت های کوکی دار آپشن L- را هم استفاده می کنند تا با ریدایرکت به سایر صفحات (مثلاً از لاگین به داشبورد) از همان کوکی های نشست استفاده شود.

curl -L -b non-existing http://example.com

با آپشن c- که در بسیاری از موارد همراه بقیه آپشن ها در نشست با یک وب سایت کوکی دار استفاده می شود می توان محتویات کوکی آن نشست را در هنگام خروج cURL (دقت کنید نه در لحظه) روی یک فایل ذخیره کرد که بعداً دوباره استفاده کرد یا هر چیز دیگر.

تصویر ذیل مثالی از کار با وب سایتی است که لاگین نیاز دارد و برای لاگین کوکی ست می کند :


مصارف متداول دیباگ لوکال (تعریف دستی IP مقصد یا مپ کردن آدرس و پورت و چک نکردن معتبر بودن certificate)

مثلاً یک سیستم وبی را داریم لوکال دیباگ می کنیم،

ممکن است نیاز شود برای تست کوکی ها یا هزار چیز دیگر ، hostname صحیح ست شده باشد یا موردی تعیین کنیم فلان دامنه به فلان IP یا دامنه اشاره دارد یا ...

به عبارت ساده مثلاً می خواهیم بدون دستکاری DNS و فایل hosts در همان نشست به cURL بگوییم منظور از مثلاً example.com آدرس 127.0.0.1 است.

برای اینکار از آپشن resolve-- با فرمت ذیل استفاده می کنیم.

--resolve [DOMAIN]:[PORT]:[IP]

همچنین برای چک نکردن معتبر بودن certificate وقتی با https کار می کنید از آپشن k- استفاده نمایید.

آپشن connect-to-- اجازه معرفی [host1][port1] و [host2][port2] را براساس نام می دهد. (نام را مپ می کند.)

curl --resolve example.com:80:127.0.0.1 http://example.com/
curl --connect-to www.example.com:80:load1.example.com:80 http://www.example.com

برای اطلاعات بیشتر دراینباره اینجا را ببینید.


تعریف Connection timeout,Network interface,Local port number,Keep alive

به مثال ها توجه بفرمایید :

Connection timeout curl --connect-timeout 2.781 https://example.com/
Network interface curl --interface eth1 https://www.example.com/ curl --interface 192.168.0.2 https://www.example.com/ curl --interface machine2 https://www.example.com/
Local port curl --local-port 4000-4200 https://example.com/
Keep alive curl --no-keepalive https://example.com/ curl --keepalive-time 300 https://example.com/


کار با IPها و خروجی های JSON

بخصوص در اسکریپت نویسی بسیار نیاز است تا اطلاعات مشخصی از یک IP را در خط فرمان بگیریم.

یکی از متداول ترین سرویس های رایگان ipinfo.io است.

اگر فقط curl ipinfo.io بزنید ، اطلاعات ip اینترنتی خودتان را باز میگرداند.

اگر curl ipinfo.io/x.x.x.x بزنید ، اطلاعات IP معرفی شده x.x.x.x را باز میگرداند.

برای گرفتن فقط یک فیلد، مثلاً فقط IP (یا هر کدام دیگر) کافیست در انتها عنوان آن فیلد را بزنید مثلا ً برای گرفتن فقط آدرس ، در انتها ip بزنید.

نسخه غیررایگان اطلاعات جامع تر و دقیق تری ارائه می دهد و محدودیت نیز ندارد.

یکی دیگر از سرویس های رایگان متداول نیز ifconfig.co است.

ممکن است نیاز داشته باشید خروجی های json تمیز بگیرید و نمایش دهید یا ذخیره کنید.

برای اینکار ابتدا ابزار jq را با yum install jq یا apt install jq نصب کنید.

به مثال ذیل توجه بفرمایید تا موضوع روشن شود :


تبدیل عملیات cURL به سورس C و برنامه اجرایی

یعنی شما یک cURLی می کنید، می فرمایید این را سورس C بکن و بعد با gcc کامپایل می کنید و یک فایل اجرایی می گیرید! با آپشن libcurl--


کپی و شبیه سازی یک request در مرورگرها با cURL

mimic that browser!

کلید f12 یا inspect را که در مرورگرهایی مثل کوروم یا فایرفاکس می زنید ، در زبانه network می توانید گزینه های مختلف copy as cURL را ببینید!

آیا تا کنون به این موضوع دقت کرده بودید؟!
آیا تا کنون به این موضوع دقت کرده بودید؟!

و خروجی هم که به کلیپ بورد کپی می شود چیزی شبیه این است که در خط فرمان یا اسکریپت خود آن را paste می کنید :

curl 'https://curl.haxx.se/' \ -H 'authority: curl.haxx.se' \ -H 'cache-control: max-age=0' \ -H 'upgrade-insecure-requests: 1' \ -H 'user-agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Mobile Safari/537.36' \ -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \ -H 'sec-fetch-site: cross-site' \ -H 'sec-fetch-mode: navigate' \ -H 'sec-fetch-user: ?1' \ -H 'sec-fetch-dest: document' \ -H 'referer: https://www.google.com/' \ -H 'accept-language: en-US,en;q=0.9,fa;q=0.8' \ -H 'cookie: _ga=GA1.2.107715833.1594721465; _gid=GA1.2.221108137.1594721465; amplitude_id_fef1e872c952688acd962d30aa545b9ehaxx.se=eyJkZXZpY2VJZCI6IjhkNWYyNGY4LWMyMGUtNGEyZC1iMTg2LTc4MDZiYTA2Y2YxMFIiLCJ1c2VySWQiOm51bGwsIm9wdE91dCI6ZmFsc2UsInNlc3Npb25JZCI6MTU5NDczNjkzMTA0NiwibGFzdEV2ZW50VGltZSI6MTU5NDczNjkzMTA1NSwiZXZlbnRJZCI6MSwiaWRlbnRpZnlJZCI6MSwic2VxdWVuY2VOdW1iZXIiOjJ9' \ -H 'if-none-match: &quot2282-5aa63f0ebdcf4-gzip&quot' \ -H 'if-modified-since: Tue, 14 Jul 2020 10:05:04 GMT' \ --compressed


ذخیره TLS Secret

مستحضر هستید که در حالت عادی مثلاً ترافیک TLS را نمی توان بصورت plain-text در مثلاً wireshark مشاهده نمود و decrypt کرد.

البته که می توان اینکار را انجام داد!

آپشن SSLKEYLOGFILE برای ذخیره TLS secrets و pre-master secretها است که در مقاله دیگری احتمالاً تحت عنوان "چگونه ترافیک HTTPS را استراق سمع کنیم؟" توضیح خواهم داد. فقط بدونید هست یا اگر هم اکنون استراق سمع TLS دارید که خودتون می دونید برای چه هست.


تعریف نسخه HTTP

در تصویر واضح است :


منابع بیشتر :

این ویدیو (توسط شخص خودش) الهام بخش عنوان و بخشی از متن و محتوی این مقاله بوده : curl better - Daniel Stenberg

Everything curl - the book

curl / Docs / Tool Documentation / HTTP Scripting : Using curl to automate HTTP jobs

curl / Docs / Tool Documentation / curl tutorial

curl / Docs / Tool Documentation / Man Page

curl / Docs / Tool Documentation / FAQ

لینوکسlinuxcurlبرنامه نویسیدیباگ
هوتن القاس پور
شاید از این پست‌ها خوشتان بیاید