برنانه نویس، مدرس، محقق. عاشق انیمه هستم و دنبال چالش ها جدید.
گرفتن IP کاربری که درخواست سمت سرور اکسپرسی فرستاده
فرض کن میخوای remote-addr رو بگیری. چکار میکنی؟ تو یه سرور واقعی، که nginx سر راه قرار داره و وب اپتون از nginx میاد بیرون.
استفاده از خود اکسپرس
اولین روشی که ممکنه اینه که بیای از هدر ریکوئست هست.
req.header('x-forwarded-for');
روش دیگه استفاده از connection هست. وقتی وب اپت پشت یه پروکسی مثل NGINX هست و پروکسی هم مال تو نیست. ممکنه هدر x-forwarded-for اسپوف (تقلبی) باشه.
req.connection.remoteAddress;
روش مطمئن تر ترکیب دو روش بالا هست. یعنی:
let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
البته ممکنه بازم با ترکیب بالا به جواب درست نرسی. چرا؟ چونکه تو خط بالایی، هدر x-forwarded-for ممکنه یه لیست از IP هایی که با کاما از هم جدا شدن برگردونه که ما معمولا IP خود کلاینت رو میخوایم. پس باید اولین مورد رو بگیریم. خب پس باید یه حرکتی برای اون موقع زد:
// x-forwarded-for = "client IP, proxy 1 IP, proxy 2 IP"
let ip = (req.headers['x-forwarded-for'] || req.connection.remoteAddress || '').split(',')[0].trim();
البته میشه یه همچین حرکتی زد:
let ip = req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress
استفاده از پکیج های third-party
برای در آوردن IP کاربر میتونی از پکیج request-ip استفاده بکنی. به عنوان یه میدلویر تعریفش میکنی برای اپت و بعدش به راحتی میگی:
app.use(requestIp.mw())
app.use((req, res, next) => { req.clientIp });
برای اینکه بگیم مزیت این پکیج چیه میتونیم یه مقدمه کوتاه بگیم. معمولا IP کاربر به ترتیب توی یکی از این هدر ها هست:
X-Client-IP
X-Forwarded-For
CF-Connecting-IP (Cloudflare)
Fastly-Client-Ip (Fastly CDN and Firebase hosting header when forwared to a cloud function)
True-Client-Ip (Akamai and Cloudflare)
X-Real-IP (Nginx proxy/FastCGI)
X-Cluster-Client-IP (Rackspace LB, Riverbed Stingray)
X-Forwarded, Forwarded-For and Forwarded (Variations of #2)
مرحله بعدی اینه که دنبال IP کاربر توی دستورای زیر بگردی:
req.connection.remoteAddress
req.socket.remoteAddress
req.connection.socket.remoteAddress
req.info.remoteAddress
خب اینا چه ربطی به مزیت این پکیج داشت؟ خب معلومه دیگه، اون پکیج میاد به ترتیب از بالا به پایین دنبال IP کاربر میگرده و اگه چیزی پیدا نکرد null بر میگردونه.
پکیج express-ip هم هست که مثل پکیج قبلی به عنوان میدلویر تعریف میشه.
پروکسی
وقتی اپ اکسپرسیت پشت یه پروکسی هست این خط کد رو به تنظیمات اپت اضافه بکن:
app.set('trust proxy', true)
اگه از یه reverse proxy استفاده نکنی میتونی از req.ip و req.ips هم استفاده بکنی. یادت باشه که همیشه نمیشه به مقدار هدر x-forwarded-for اعتماد کرد. (مثلا اگه پروکسی شما هدر هایی که از قبل وجود دارن رو از سورس های untrusted پاک نمیکنه.)
تنظیمات فایل nginx سایت
البته باید یادت باشه که یه چیزی رو توی تنظیمات NGINX باید تغیر بدی. اونم اینه که توی فایلی که تو این مسیر (/etc/nginx/sites-available/) برای کانفیگای سرورت ایجاد کردی این خطو اضافه بکنی.
proxy_set_header X-Real-IP $remote_addr;
این خط یعنی چی؟ وقتی شما از یه reverse proxy استفاده میکنی ممکنه اون reverse proxy نیاد اطلاعات درخواست رو پخش بکنه و در اختیار وب سرور بعد ازخودش قرار بده. پس ما هم خط بالایی رو به nginx اضافه میکنیم. مثلا فایل نهایی تقریبا این شکلی میشه:
// file path: /etc/nginx/sites-available/www.example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.1.1:3080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
تنظیمات nignx
میتونی به جای اون حرکت قبلی بیای این کار رو بکنی که تنظیمات خود nginx رو تو فایل nginx.conf عوض بکنی و این خطو به تنظیماتش اضافه بکنی:
proxy_set_header X-Real-IP $remote_addr;
و بعدش توی اپ اکسپرسیت بیای اینو بنویسی:
let ip = req.headers['x-real-ip'] || req.connection.remoteAddress;
خب همین بود دیگه. اگه چیزی دیگه ای فهمیدم اضافه میکنم. در کل منتظر اپدیت باش.
مطلبی دیگر از این انتشارات
حقوق،جایگاه و بازار کار برنامه نویسی
مطلبی دیگر از این انتشارات
در باب خصوصیات پروژهای که آن را Legacy مینامیم | قسمت دوم |
مطلبی دیگر از این انتشارات
اصول برنامه نویسی خوب - !YAGNI- شما به آن احتیاج ندارید!