
একটি ওয়েবসাইট বানানোর পর আমরা ডিজাইন নিয়ে ভাবি, স্পিড নিয়ে ভাবি, এসইও নিয়ে ভাবি। কিন্তু সার্ভার প্রতিবার ব্রাউজারকে যে কয়েকটা নীরব নির্দেশ পাঠায়, সেগুলো নিয়ে প্রায় কেউ ভাবে না। ওই নির্দেশগুলোর নাম HTTP সিকিউরিটি হেডার। এগুলো ঠিকভাবে বসানো থাকলে ক্লিকজ্যাকিং, MIME স্নিফিং, স্ক্রিপ্ট ইনজেকশনের মতো কয়েক ধরনের আক্রমণ ব্রাউজার নিজেই আটকে দেয়। না থাকলে ব্রাউজার আপনার হয়ে কিছুই আটকায় না।
ভালো খবর হলো এই হেডারগুলো বসাতে কোনো টাকা লাগে না, কোনো প্লাগিন কিনতে হয় না, আর কাজটা আধা ঘণ্টার। এই টিউনে আমরা প্রথমে একটি সাইটের আসল গ্রেড দেখব, তারপর ছয়টি হেডার এক এক করে বুঝব, শেষে Nginx, Apache আর WordPress এর জন্য বসানোর কোড দেখব। সব ধাপে আসল স্ক্রিনশট দেওয়া আছে।
ব্রাউজার যখন আপনার সাইট খোলে, সার্ভার শুধু HTML পাঠায় না, তার সাথে একগুচ্ছ হেডারও পাঠায়। কিছু হেডার বলে ফাইলটির ধরন কী, কিছু বলে কতক্ষণ ক্যাশে রাখা যাবে। সিকিউরিটি হেডারগুলো বলে ব্রাউজার কী কী করতে পারবে না। যেমন আপনার পেজটি অন্য কারো সাইটে ফ্রেমের ভেতরে দেখানো যাবে কি না, কোন কোন জায়গা থেকে স্ক্রিপ্ট লোড করা যাবে, বা ক্যামেরা ব্যবহারের অনুমতি চাওয়া যাবে কি না। ব্রাউজার এই নিষেধাজ্ঞাগুলো মেনে চলে, তাই এগুলো খুব শক্তিশালী।
কাজ শুরুর আগে জানা দরকার এখন কী অবস্থা। securityheaders.com এ গিয়ে সাইটের ঠিকানা বসিয়ে Scan চাপলেই কয়েক সেকেন্ডে A থেকে F পর্যন্ত একটি গ্রেড পাওয়া যায়। উদাহরণ হিসেবে একটি বড় সাইট স্ক্যান করে দেখা গেল ফল কী আসে।

গ্রেড A এসেছে কারণ ছয়টি প্রধান হেডারের মধ্যে পাঁচটিই বসানো আছে। শুধু Permissions-Policy নেই, তাই সেটি লাল দেখাচ্ছে। ছয়টিই থাকলে গ্রেড A প্লাস পর্যন্ত উঠতে পারে। মনে রাখবেন, এই গ্রেড শুধু হেডার দেখে দেওয়া হয়, এটি পুরো সাইটের নিরাপত্তার সার্টিফিকেট নয়।
রিপোর্টে তিনটি অংশ থাকে। উপরে Security Report Summary, যেখানে গ্রেড ও হেডারের তালিকা। মাঝে Missing Headers, যেখানে যেগুলো নেই তাদের ব্যাখ্যা। নিচে Raw Headers, যেখানে সার্ভার আসলে কী পাঠিয়েছে তার হুবহু তালিকা। কাজ করার সময় সবচেয়ে বেশি দরকার হবে শেষ অংশটি, কারণ সেখানেই আসল মান দেখা যায়।

এখানে দেখা যাচ্ছে HSTS এর মান এক বছরের সমান, সাবডোমেইনও এর আওতায় আছে, এবং preload তালিকায় নাম দেওয়া আছে। X-Frame-Options এ deny বসানো, X-Content-Type-Options এ nosniff বসানো। নিজের সাইটে কাজ করার পর ঠিক এভাবেই মিলিয়ে দেখবেন।
অনেকের সাইট প্রথম স্ক্যানেই F পায়। এতে ঘাবড়ানোর কিছু নেই, কারণ ডিফল্ট অবস্থায় কোনো সার্ভারই এই হেডারগুলো নিজে থেকে পাঠায় না। কেমন দেখায় সেটি বোঝার জন্য একটি নিরপেক্ষ টেস্ট ডোমেইন স্ক্যান করা হয়েছে।

লক্ষ্য করুন গ্রেডের ঘরটি লাল হয়ে গেছে এবং ছয়টি হেডারের পাশেই ক্রস চিহ্ন। এই সাইটে HTTPS আছে, TLS সার্টিফিকেট আছে, তবু গ্রেড F। অর্থাৎ HTTPS থাকা আর সিকিউরিটি হেডার থাকা দুটি আলাদা বিষয়, একটি দিয়ে অন্যটির কাজ হয় না।
এই টুলের সবচেয়ে কাজের দিক হলো Missing Headers অংশ। যেটি নেই তার পাশে ছোট করে লেখা থাকে হেডারটি কী কাজ করে এবং সুপারিশকৃত মান কী হওয়া উচিত।

এখান থেকেই বোঝা যায় HSTS এর সুপারিশকৃত মান কত সেকেন্ড, আর CSP কীভাবে ক্ষতিকর স্ক্রিপ্ট লোড হওয়া বন্ধ করে। কাজ শুরুর আগে এই অংশটুকু একবার মন দিয়ে পড়ে নিলে বাকিটা সহজ হয়ে যায়।
Strict-Transport-Security বা সংক্ষেপে HSTS ব্রাউজারকে বলে দেয় এই সাইটে শুধু HTTPS দিয়েই ঢোকা যাবে। একবার এই হেডার দেখলে ব্রাউজার নির্দিষ্ট সময় পর্যন্ত মনে রাখে, এবং কেউ যদি ভুলে http দিয়ে ঠিকানা লেখে তাহলে ব্রাউজার নিজেই সেটিকে https বানিয়ে নেয়। মাঝপথে বসে থাকা কেউ আর সেই অনুরোধ ছিনিয়ে নিতে পারে না।
কোনো হেডার নিয়ে সন্দেহ হলে ব্লগ না খুঁজে সরাসরি MDN Web Docs এ চলে যাওয়া ভালো। সেখানে প্রতিটি হেডারের সিনট্যাক্স, ডিরেক্টিভ, উদাহরণ ও ব্রাউজার সাপোর্ট এক পেজেই থাকে।

উপরের সবুজ বাক্সে Baseline লেখা অংশটি খুব কাজের। ওটি দেখেই বোঝা যায় হেডারটি ক্রোম, এজ, ফায়ারফক্স ও সাফারি সব জায়গায় সমর্থিত কি না। নতুন কোনো হেডার বসানোর আগে এই অংশ দেখে নেওয়া অভ্যাস করে ফেলুন।
HSTS তিনভাবে লেখা যায়। শুধু max-age দিয়ে, সাথে includeSubDomains যোগ করে, অথবা তার সাথে preload যোগ করে। MDN এ তিনটি রূপ পাশাপাশি দেওয়া আছে।

একটি সতর্কবার্তা আছে। preload যোগ করে ব্রাউজারের তালিকায় নাম ঢোকালে সেটি থেকে বেরিয়ে আসা খুব কঠিন ও সময়সাপেক্ষ। তাই আপনার সাইট ও সব সাবডোমেইন যতক্ষণ পুরোপুরি HTTPS এ না আসে, ততক্ষণ preload দেবেন না। শুরুতে max-age কম রেখে পরীক্ষা করুন, সব ঠিক থাকলে তখন বাড়িয়ে নিন।
ক্লিকজ্যাকিং আক্রমণে আক্রমণকারী নিজের পেজে আপনার সাইটটিকে অদৃশ্য ফ্রেমে বসিয়ে দেয়। ব্যবহারকারী ভাবে সে আক্রমণকারীর বোতামে ক্লিক করছে, আসলে ক্লিক পড়ছে আপনার সাইটের বোতামে। X-Frame-Options এ SAMEORIGIN বসালে শুধু আপনার নিজের ডোমেইন থেকেই ফ্রেমে বসানো যাবে। কেউ ফ্রেমে না বসালে DENY দেওয়াই সবচেয়ে নিরাপদ।
সার্ভার বলল ফাইলটি সাধারণ টেক্সট, কিন্তু ব্রাউজার ভেতরে উঁকি দিয়ে ভাবল এটি আসলে স্ক্রিপ্ট, তারপর সেটি চালিয়ে দিল। এই আচরণকে বলে MIME স্নিফিং, আর এটি আপলোড ফোল্ডার থাকা সাইটের জন্য বিপদ। nosniff মান বসালে ব্রাউজার আর অনুমান করে না, সার্ভার যা বলেছে সেটাই মানে। এই হেডারটির মান একটিই, তাই ভুল করার সুযোগও নেই।
আপনার সাইট থেকে কেউ বাইরের কোনো লিংকে ক্লিক করলে ব্রাউজার ওই সাইটকে জানিয়ে দেয় সে কোন ঠিকানা থেকে এসেছে। ঠিকানায় যদি সার্চ শব্দ বা আইডি থাকে, সেটিও চলে যায়। Referrer-Policy তে strict-origin-when-cross-origin বসালে বাইরের সাইট শুধু আপনার ডোমেইন নাম জানবে, পুরো পথ জানবে না। এটি এখন বেশিরভাগ ব্রাউজারের ডিফল্ট, তবু স্পষ্ট করে বসানো ভালো।
CSP দিয়ে বলে দেওয়া যায় স্ক্রিপ্ট, ছবি, ফন্ট বা স্টাইল কোথা থেকে লোড হতে পারবে। ঠিকভাবে বসালে স্ক্রিপ্ট ইনজেকশনের বড় অংশ এতেই আটকে যায়। কিন্তু এটিই একমাত্র হেডার যেটি ভুল হলে সাইট দেখতে ভেঙে যেতে পারে, কারণ আপনার নিজের দরকারি ফাইলও ব্লক হয়ে যেতে পারে। তাই শুরুতে খুব ঢিলে একটি নীতি দিয়ে শুরু করুন, তারপর ধীরে ধীরে কড়া করুন।
Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self'; frame-ancestors 'self'
সরাসরি CSP চালু না করে প্রথমে Content-Security-Policy-Report-Only নামের হেডারটি একই মান দিয়ে বসান। এতে কিছুই ব্লক হবে না, শুধু ব্রাউজার কনসোলে জানিয়ে দেবে কোন কোন জিনিস ব্লক হতো। কয়েক দিন দেখে তালিকা পরিষ্কার হলে তখন আসল হেডারে বদলে নিন।
এই হেডার দিয়ে বলে দেওয়া যায় আপনার পেজ থেকে ক্যামেরা, মাইক্রোফোন বা লোকেশন ব্যবহারের অনুমতি চাওয়া যাবে কি না। সাধারণ ব্লগ বা ইকমার্স সাইটে এই তিনটির কোনোটিরই দরকার নেই, তাই সব বন্ধ করে দেওয়াই যুক্তিযুক্ত। বিজ্ঞাপণ বা তৃতীয় পক্ষের কোনো স্ক্রিপ্ট যদি আপনার অজান্তে অনুমতি চাইতে যায়, এতে সেটিও আটকে যাবে।
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
পুরোনো অনেক বাংলা লেখায় দেখবেন X-XSS-Protection হেডারে এক বসানোর পরামর্শ দেওয়া আছে। ওই পরামর্শ এখন আর ঠিক নয়। আধুনিক ব্রাউজারগুলো এই ফিল্টার তুলে দিয়েছে, কারণ কিছু ক্ষেত্রে এটি নিজেই নতুন দুর্বলতা তৈরি করত। এখন সুপারিশ হলো মান শূন্য দিয়ে ফিল্টারটি স্পষ্টভাবে বন্ধ রাখা এবং তার বদলে CSP এর উপর ভরসা করা। আগের স্ক্রিনশটেও দেখবেন বড় সাইটটি ঠিক এই কাজটিই করেছে, অর্থাৎ শূন্য বসিয়ে রেখেছে। পুরোনো টিউটোরিয়াল দেখে কাজ করার আগে তাই MDN এ একবার মিলিয়ে নেওয়া জরুরি, কারণ ওয়েব স্ট্যান্ডার্ড প্রতি বছরই বদলায়।
Nginx ব্যবহার করলে সাইটের কনফিগ ফাইলে server ব্লকের ভেতরে নিচের লাইনগুলো বসিয়ে দিন। always শব্দটি জরুরি, না দিলে এরর পেজে হেডার যায় না।
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
কোড বসানোর পর কনফিগ পরীক্ষা করে তারপর রিলোড দিন। পরীক্ষা না করে রিলোড দিলে ছোট একটি টাইপো পুরো সার্ভার নামিয়ে দিতে পারে।
nginx -t systemctl reload nginx
শেয়ার্ড হোস্টিং এ সাধারণত Apache থাকে এবং সার্ভার কনফিগে হাত দেওয়ার সুযোগ থাকে না। সেক্ষেত্রে ওয়েব রুটে থাকা htaccess ফাইলে নিচের লাইনগুলো যোগ করলেই কাজ হয়ে যায়। এগুলো mod_headers মডিউলের IfModule ব্লকের ভেতরে রাখা সবচেয়ে নিরাপদ, কারণ মডিউলটি বন্ধ থাকলে সাইটে এরর আসবে না।
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
সার্ভার কনফিগে একেবারেই হাত না দিতে পারলে PHP দিয়েও হেডার পাঠানো যায়। চাইল্ড থিমের functions ফাইলে নিচের কোডটি বসিয়ে দিন। মনে রাখবেন এই পদ্ধতিতে হেডার শুধু PHP দিয়ে তৈরি পেজে যায়, সরাসরি লোড হওয়া ছবি বা CSS ফাইলে যায় না। তাই সুযোগ থাকলে সার্ভার লেভেলই ভালো।
function tt_security_headers($headers) {$extra = array("X-Frame-Options" => "SAMEORIGIN",
"X-Content-Type-Options" => "nosniff",
"Referrer-Policy" => "strict-origin-when-cross-origin");
return array_merge($headers, $extra);}
add_filter("wp_headers", "tt_security_headers");
প্রথম ভুল হলো একই হেডার দুবার পাঠানো। সার্ভার আর প্লাগিন দুই জায়গা থেকে পাঠালে ব্রাউজার বিভ্রান্ত হয়। দ্বিতীয় ভুল হলো HTTPS ঠিকঠাক না করেই বড় max-age দিয়ে HSTS চালু করা, এতে সাইট কিছুদিনের জন্য অচল হয়ে যেতে পারে। তৃতীয় ভুল হলো CSP তে নিজের CDN বা ফন্টের ঠিকানা যোগ না করা, ফলে ডিজাইন ভেঙে পড়ে। চতুর্থ ভুল হলো X-Frame-Options এ DENY দিয়ে দেওয়া অথচ নিজের সাইটেই কোনো পেজ ফ্রেমে দেখানো হচ্ছে।
হেডার বসানোর পর ক্যাশ পরিষ্কার করে আবার securityheaders.com এ স্ক্যান করুন। যদি পুরোনো ফল দেখায়, তার মানে সাইটের সামনে থাকা CDN বা ক্যাশ এখনো পুরোনো হেডার পাঠাচ্ছে। CDN এর ক্যাশ খালি করে আবার দেখুন। ছয়টির মধ্যে যতগুলো সবুজ হবে গ্রেড ততই উপরে উঠবে। সব সবুজ হলে A প্লাস পর্যন্ত পাওয়া সম্ভব।
সাইট পুরোপুরি HTTPS এ আছে কি, এটি আগে নিশ্চিত করুন। এরপর ছয়টি হেডার বসিয়ে কনফিগ পরীক্ষা করুন। এরপর CSP আগে রিপোর্ট মোডে চালিয়ে কনসোল দেখুন। এরপর একই হেডার কোথাও দুবার যাচ্ছে কি না মিলিয়ে দেখুন। সবশেষে মোবাইল ও ডেস্কটপ দুই জায়গা থেকে সাইট ঘুরে দেখুন কিছু ভেঙেছে কি না।
সিকিউরিটি হেডার এমন এক কাজ যেটি একবার ঠিকভাবে করলে বছরের পর বছর নীরবে কাজ করে যায়। কোনো মাসিক খরচ নেই, সাইটের গতিও কমে না, অথচ কয়েক ধরনের আক্রমণ ব্রাউজার নিজেই আটকে দেয়। আজ নিজের সাইটটি স্ক্যান করে দেখুন কী গ্রেড আসে, তারপর এক এক করে হেডার বসিয়ে আবার স্ক্যান করুন। আপনার সাইটে প্রথম স্ক্যানে কী গ্রেড এল তা টিউমেন্টে জানাতে পারেন।
আমি নাছিরুল হক। বিশ্বের সর্ববৃহৎ বিজ্ঞান ও প্রযুক্তির সৌশল নেটওয়ার্ক - টেকটিউনস এ আমি 2 দিন 17 ঘন্টা যাবৎ যুক্ত আছি। টেকটিউনস আমি এ পর্যন্ত 15 টি টিউন ও 0 টি টিউমেন্ট করেছি। টেকটিউনসে আমার 0 ফলোয়ার আছে এবং আমি টেকটিউনসে 0 টিউনারকে ফলো করি।
আমি নাছিরুল হক। প্রোগ্রামিং আর প্রযুক্তি নিয়ে ঘাঁটাঘাঁটি করতে ভালোবাসি। টেকটিউনসে মূলত Java প্রোগ্রামিং নিয়ে ধাপে ধাপে হাতে কলমে টিউটোরিয়াল লিখি — JDK ইনস্টল ও এনভায়রনমেন্ট সেটআপ থেকে শুরু করে IntelliJ IDEA, Exception Handling, OOP, Java Swing ও ফাইল হ্যান্ডলিং পর্যন্ত। এছাড়া স্মার্টফোন, ব্যাটারি ও নেটওয়ার্ক নিয়ে সহজ ভাষায় ব্যাখ্যামূলক...