SELinux ও firewalld দিয়ে SSH port পরিবর্তনের নিয়ম
Rocky Linux বা AlmaLinux-এ SSH port বদলাতে firewalld, SELinux port label ও sshd_config এই ক্রমে সেট করুন, যাতে বর্তমান session বন্ধ না হয়।
এখানে SSH port পরিবর্তনের জন্য তিনটি ধাপ প্রয়োজন
Rocky Linux, AlmaLinux, CentOS Stream বা Fedora-তে SSH port পরিবর্তন করতে শুধু একটি edit যথেষ্ট নয়। নতুন port-এ connection কাজ করবে কি না, তা তিনটি পৃথক system নির্ধারণ করে। firewalld ঠিক করে packet মেশিনে পৌঁছাবে কি না। SELinux ঠিক করে sshd ওই port number-এ bind করার অনুমতি পাবে কি না। sshd_config ঠিক করে daemon কোন port-এর জন্য অনুরোধ করবে। SELinux-এর ধাপ বাদ দিলে daemon start হতে অস্বীকার করে। firewalld-এর ধাপ বাদ দিলে daemon start হয়ে listening অবস্থায় থাকে, কিন্তু কেউ সেখানে পৌঁছাতে পারে না।
Ubuntu-তে একই কাজের জন্য একটি edit এবং একটি restart যথেষ্ট, কারণ Ubuntu SELinux-এর পরিবর্তে AppArmor ব্যবহার করে এবং sshd কোন port-এ bind করতে পারবে তা সীমিত করার কোনো profile defaultভাবে দেয় না। সেখানে ufw চালু থাকলে একটি rule যোগ করতে হবে। এটিই পুরো পার্থক্য। RHEL family fresh install-এ firewalld চালু এবং SELinux enforcing অবস্থায় দেয়, আর উভয় system-ই port number বিবেচনা করে।
এই ক্রমে কাজ করুন, তাহলে প্রতিটি ধাপের সময় আপনার বর্তমান session চালু থাকবে:
- নতুন port firewalld-এ খুলুন, তবে আপাতত port 22 খোলা রাখুন।
semanageব্যবহার করে নতুন port-এর জন্য SELinux label যোগ করুন।- sshd configuration-এ port নির্ধারণ করুন।
sshdrestart করুন। এরপর প্রথম terminal বন্ধ করার আগে দ্বিতীয় terminal থেকে নতুন port-এ login করুন।
কাজ শুরু করার আগে আপনার provider-এর web console (VNC বা serial) খুঁজে বের করুন এবং সেটির মাধ্যমে login করতে পারছেন কি না পরীক্ষা করুন। পরিবর্তনটি ভুল হলে ওই console-ই server-এ পুনরায় প্রবেশের আপনার উপায়। সদ্য ভাড়া নেওয়া server-এ tenant নিজেই access হারিয়ে ফেলার সবচেয়ে সাধারণ কারণগুলোর একটি হলো port পরিবর্তন।
প্রথমে semanage ইনস্টল করুন
semanage হলো SELinux policy settings সম্পাদনা করার tool। Minimal Rocky Linux বা AlmaLinux install-এ এটি থাকে না। এটি policycoreutils-python-utils-এর মধ্যে থাকে।
sudo dnf install -y policycoreutils-python-utilsPackage ইনস্টল করার আগে command চালালে sudo: semanage: command not found দেখা যায়। এই পর্যায়ে অনেক পাঠক ধরে নেন যে SELinux ইনস্টল করা নেই এবং ধাপটি এড়িয়ে যান। SELinux ইনস্টল করা আছে। শুধু management tool-টি অনুপস্থিত। dnf syntax আপনার কাছে নতুন হলে, dnf এবং apt command-এর সমতুল্য আপনার পরিচিত command-এর সঙ্গে মিলিয়ে দেখুন।
একটি port নির্বাচন করে সেটি কোনো process ব্যবহার করছে কি না পরীক্ষা করুন
1024 থেকে 65535-এর মধ্যে যেকোনো free TCP port ব্যবহার করা যাবে। একটি port চূড়ান্ত করার আগে দুটি পরীক্ষা করুন:
sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222প্রথম কমান্ডটি দেখায়, ওই port number-এ কোনো process ইতিমধ্যে listening করছে কি না। দ্বিতীয়টি দেখায়, SELinux policy সেটি অন্য কোনো service type-এর জন্য নির্ধারণ করেছে কি না। Free port হলে কোনো কমান্ড থেকেই output পাওয়া যাবে না। Policy যদি port-টি আগে থেকেই বরাদ্দ করে থাকে, তাহলে ধাপ 2-এর semanage port -a কমান্ডটি ValueError: Port tcp/2222 already defined error-এ ব্যর্থ হবে। সে ক্ষেত্রে অন্য port number নির্বাচন করুন।
এই guide-এ উদাহরণ হিসেবে 2222 ব্যবহার করা হয়েছে। 22-এর পর scanner সাধারণত এটিই প্রথমে পরীক্ষা করে। তাই বাস্তব server-এ আরও কম obvious কোনো port নির্বাচন করুন।
ধাপ 1: firewalld-এ port খুলুন
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports--permanent disk-এ থাকা zone file-এ rule লিখে, কিন্তু চলমান firewall-এ কোনো পরিবর্তন করে না। --reload disk-এ থাকা configuration চলমান firewall-এ load করে। reload বাদ দিলে rule তৈরি হয়, কিন্তু firewalld পরবর্তীবার restart না হওয়া পর্যন্ত সেটি কোনো কাজ করে না। কোনো স্পষ্ট কারণ ছাড়াই পুরো প্রক্রিয়াটি ব্যর্থ হয়েছে বলে মনে হওয়ার সবচেয়ে সাধারণ কারণগুলোর একটি এটি।
এখন ssh service entry অপরিবর্তিত রাখুন। এই entry-ই port 22 খোলা রাখে এবং পরীক্ষা করার সময় এটি আপনার fallback হিসেবে কাজ করবে।
আপনার provider-এর control panel-ও পরীক্ষা করুন। অনেক host operating system-এর বাইরে VPS-এর সামনে একটি network firewall চালায়। তাই firewalld-এ খোলা port upstream-এ এখনও drop হতে পারে। এই মডেলটি নতুন হলে VPS-এর firewalld-এর মৌলিক নির্দেশিকা-এ zones এবং runtime বনাম permanent configuration-এর বিভাজন ব্যাখ্যা করা হয়েছে।
ধাপ 2: SELinux-এর জন্য port label নির্ধারণ করুন
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t-a একটি নতুন port assignment যোগ করে। -t ssh_port_t হলো SSH port-এ ব্যবহৃত type। দ্বিতীয় command-টি এখন ssh_port_t-এর আওতায় থাকা সবকিছু তালিকাভুক্ত করে। তাই daemon-এ পরিবর্তন করার আগে আপনার port number যোগ হয়েছে কি না নিশ্চিত করতে পারেন।
SELinux কেন port-এ সংযোগ আটকে দেয়
SELinux (security-enhanced Linux) সিস্টেমের প্রতিটি object-এ একটি label নির্ধারণ করে। TCP port number-ও অন্যান্য object-এর মতো label-যুক্ত object। SSH daemon sshd_t নামের একটি domain-এ সীমাবদ্ধ অবস্থায় চলে। Policy অনুযায়ী sshd_t-এর ssh_port_t label-যুক্ত TCP port-এ bind করার অনুমতি আছে। ডিফল্টভাবে এই label-যুক্ত একমাত্র port হলো 22। Daemon-কে 2222 port-এ bind করতে বললে kernel label পরীক্ষা করে। ওই port number-এ policy যে generic type নির্ধারণ করেছে, তা শনাক্ত করার পর kernel socket-এ name_bind permission প্রত্যাখ্যান করে।
এ কারণেই এই ব্যর্থতা firewall সমস্যার মতো দেখায় না। Listening socket তৈরি হওয়ার আগেই kernel অনুরোধ প্রত্যাখ্যান করে। ফলে sshd error দেখিয়ে বন্ধ হয়ে যায়। Firewall সমস্যার ক্ষেত্রে চিত্রটি বিপরীত। Daemon চলমান ও সুস্থ থাকে, কিন্তু আসা network packet পথে বাতিল হয়।
getenforce সিস্টেমটি কোন mode-এ চলছে তা জানায়। Permissive-এ denial record করা হয়, কিন্তু তা কার্যকরভাবে প্রয়োগ করা হয় না। তাই port পরিবর্তনটি প্রথমে কাজ করে বলে মনে হয়। পরে কেউ setenforce 1 চালালে বা সিস্টেমটি reboot হয়ে enforcing mode-এ গেলে তা ব্যর্থ হয়। যেকোনো mode-এই port-এ সঠিক label নির্ধারণ করুন। সার্ভারের জন্য SELinux-এর মৌলিক নির্দেশিকা mode, context এবং boolean বিস্তারিতভাবে ব্যাখ্যা করে।
ধাপ 3: sshd কনফিগারেশনে port নির্ধারণ করুন
Rocky Linux 9 ও 10, AlmaLinux 9 ও 10 এবং বর্তমান Fedora-তে /etc/ssh/sshd_config একটি include line দিয়ে শুরু হয়। তাই পরিবর্তনের জন্য drop-in file ব্যবহার করাই সুশৃঙ্খল পদ্ধতি। এরপর package update আপনার সম্পাদনার সঙ্গে আর বিরোধ করবে না।
grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -tgrep-এ কোনো Include line না থাকলে, যেমন Rocky Linux 8 এবং অন্যান্য পুরোনো image-এ দেখা যায়, সরাসরি /etc/ssh/sshd_config-এ Port 2222 যোগ করুন। sshd -t drop-in-সহ পুরো configuration parse করে এবং syntax error জানায়। restart করার আগে এটি জানানো সব সমস্যা ঠিক করুন। কারণ configuration parse করতে ব্যর্থ হলে daemon আর চালু হবে না।
Port একাধিকবার থাকতে পারে এবং sshd তালিকাভুক্ত প্রতিটি port-এ listen করে। প্রথম দিন Port 2222-এর পাশাপাশি Port 22 রেখে দেওয়া একটি সহজ safety net, তবে পরে এটি সরিয়ে ফেলতে ভুলবেন না।
আপনার sshd কি socket unit দ্বারা চালু হয়?
কিছু image দীর্ঘ সময় চলমান service হিসেবে নয়, systemd socket activation ব্যবহার করে SSH চালু করে। এভাবে সেট করা থাকলে systemd listening socket-এর মালিকানা ধরে রাখে এবং সংযোগ sshd-এর কাছে পাঠায়। তাই Port-এর sshd_config লাইনটি সম্পূর্ণ উপেক্ষিত হয়। কোনো কিছু restart করার আগে পরীক্ষা করুন:
systemctl is-enabled sshd.socketenabled-এর উত্তর enabled হলে port-টি sshd_config-এ নয়, socket unit-এ নির্ধারিত আছে:
sudo systemctl edit sshd.socket[Socket]
ListenStream=
ListenStream=2222খালি ListenStream= প্রয়োজন। drop-in-গুলোর মাধ্যমে মান জমা হয়। তাই তালিকা পরিষ্কার করার জন্য আগে খালি assignment না দিলে socket 2222-এর পাশাপাশি 22 port-এও listening চালিয়ে যাবে। sudo systemctl daemon-reload ব্যবহার করে এটি প্রয়োগ করুন, তারপর sudo systemctl restart sshd.socket চালান। আপনার server-এ unit-টি disabled থাকলে বা উপস্থিত না থাকলে এই section আপনার ক্ষেত্রে প্রযোজ্য নয়।
ধাপ 4: restart করুন, তারপর দ্বিতীয় terminal থেকে পরীক্ষা করুন
sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshdএই terminal-টি খোলা রাখুন। এটি থেকে log out করবেন না। নিজের মেশিনে একটি দ্বিতীয় terminal খুলে নতুন port-এ connect করুন:
ssh -p 2222 youruser@203.0.113.10দ্বিতীয় login সফল হওয়ার পরেই কেবল প্রথম session বন্ধ করুন। এটি কাজ না করলে আপনার কাছে এখনও এমন একটি shell থাকবে, যেখান থেকে সব পরিবর্তন পূর্বাবস্থায় ফেরাতে পারবেন। এই অভ্যাসের কারণেই পাঁচ মিনিটের একটি পরিবর্তন এবং provider console-এ কাটানো পুরো একটি বিকেলের মধ্যে পার্থক্য তৈরি হয়।
Firewall drop নাকি SELinux denial? কীভাবে পার্থক্য করবেন
আপনার laptop থেকে দুটি ব্যর্থতা প্রায় একই রকম দেখায়। কিন্তু server-এ এগুলোর চেহারা সম্পূর্ণ আলাদা।
- যদি
systemctl status sshdদেখায় যে unit ব্যর্থ হয়েছে, তাহলে daemon তার socket পায়নি। এটি configuration error অথবা SELinux denial। - যদি unit active থাকে এবং
ss -tlnpদেখায় যে sshd নতুন port-এ bind করেছে, তাহলে daemon ঠিক আছে। সমস্যা network path-এ: firewalld, provider-এর আলাদা firewall, অথবা আপনি যে address ও port-এ সংযোগ করেছেন সেখানে।
SELinux-এর ক্ষেত্রে অনুমান না করে audit record পড়ুন:
sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pagerclass tcp_socket-এর ওপর একটি name_bind denial-এ comm="sshd"-এ process, src=-এ port number এবং tcontext=-এ port-এ বর্তমানে থাকা label উল্লেখ থাকে। শেষের field-টিই উত্তর দেয়। ssh_port_t ছাড়া অন্য কিছু থাকলে আপনি যে port ব্যবহার করছেন তাতে step 2 প্রযোজ্য হয়নি। সাধারণত port number-এ typo থাকে অথবা ভুল protocol ব্যবহার করা হয়। আপনি যদি sealert-কে record-টি একটি বাক্যে রূপান্তর করতে দিতে চান, তাহলে setroubleshoot-server install করুন।
Kernel bind করতে অস্বীকার করলে sshd নিজে যে message লেখে, তা এমন দেখায়:
error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.1024-এর বেশি port-এ Permission denied, যেখানে bind করার জন্য root privilege প্রয়োজন হয় না, SELinux-এর স্বাক্ষর। একই line-এ Address already in use একটি ভিন্ন সমস্যা নির্দেশ করে: অন্য একটি process port-টি ধরে রেখেছে। Client side থেকে connection refused এবং connection timed out-এর পার্থক্য দুটি network case আলাদা করে, কারণ refusal-এর অর্থ আপনার packet host-এ পৌঁছেছে কিন্তু কোনো কিছু listening করেনি; timeout-এর অর্থ একেবারেই কোনো উত্তর আসেনি।
22 port বন্ধ করুন এবং client আপডেট করুন
নতুন port-এ একাধিক login সফল হলে 22 port-এর প্রবেশপথ বন্ধ করুন:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all22 port-এর SELinux label পরিবর্তন করবেন না। এটি base policy থেকে আসে। Firewall packet প্রবেশ বন্ধ করলে এই label আর কোনো অনুমতি দেয় না।
এরপর client-গুলো ঠিক করুন। কারণ default port ধরে নেওয়া প্রতিটি tool-কে এখন নতুন port জানাতে হবে। বারবার -p লেখার বদলে নিজের মেশিনে একবার ~/.ssh/config-এ এটি যোগ করুন:
Host myvps
HostName 203.0.113.10
Port 2222
User youruserscp, sftp, rsync এবং Ansible—সবই ওই file পড়ে। কিন্তু port 22 hardcode করা backup job, monitoring check এবং cron script-গুলো এটি পড়ে না। তাই পরিবর্তনটি সদ্য মনে থাকতেই সেগুলো খুঁজে আপডেট করুন।
Port পরিবর্তন করলে কী লাভ হয় এবং কী হয় না
এতে log-এর অপ্রয়োজনীয় noise কমে। Automated scanner-গুলো নিয়মিত port 22-এ ব্যাপকভাবে scan চালায়। port পরিবর্তন করলে journal-এ ওই ধরনের line-এর বেশির ভাগ আর থাকে না। ফলে প্রকৃত event সহজে দেখা যায়। এটি কোনো security control নয়। যে scanner সম্পূর্ণ port range scan করে, সেটি আপনার daemon খুঁজে পাবে এবং তার version banner-ও পড়তে পারবে। Port পরিবর্তনকে শুধু housekeeping হিসেবে বিবেচনা করুন। প্রকৃত সুরক্ষা দিন password login বন্ধ করে key-only authentication চালু করার মাধ্যমে। এই প্রক্রিয়াটি VPS-এর SSH hardening guide-এ ধাপে ধাপে দেখানো হয়েছে।
উপরের সবকিছুই প্রধান দুই RHEL rebuild-এ একইভাবে কাজ করে, কারণ এগুলো একই source থেকে তৈরি। কোনটি বেছে নেবেন তা এখনও ঠিক না করলে Rocky Linux এবং AlmaLinux-এর তুলনা দেখুন। পুরোনো কোনো guide অনুসরণ করার আগে cat /etc/os-release ব্যবহার করে আপনি আসলে কোন release পেয়েছেন তা যাচাই করুন। Rocky Linux 8-এর জন্য লেখা guide-গুলো এখনও search result-এ ভালো অবস্থানে থাকে এবং সেগুলোর semanage ও firewall-cmd ধাপ এখনও সঠিক। তবে Rocky 8-এ কোনো sshd_config.d include line নেই এবং socket unit নিয়েও ভাবতে হয় না। তাই ওই guide-গুলোর sshd অংশ বর্তমান box-এর সঙ্গে মেলে না।
fail2ban-কে নতুন port সম্পর্কে জানাতে হবে
fail2ban base repository-তে নেই। এটি EPEL (enterprise Linux-এর অতিরিক্ত package) থেকে আসে:
sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalldfail2ban-firewalld subpackage fail2ban-কে firewalld-এর মাধ্যমে ban প্রয়োগ করতে দেয়। firewalld ruleset নিয়ন্ত্রণ করে এমন server-এ এটিই প্রয়োজনীয়।
Stock sshd jail-এ port = ssh সেট করা থাকে। এই নামটি /etc/services-এর মাধ্যমে 22-এ resolve হয়। পরিবর্তনের পরে jail এমন একটি port monitor করে যেটিতে কেউ আক্রমণ করছে না। তাই 2222-এ failed login জমা হলেও এটি কাউকে ban করে না। /etc/fail2ban/jail.local-এ port নম্বর দিয়ে সেট করুন:
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600backend = systemd /var/log/secure থেকে নয়, journal থেকে failure পড়ে। Minimal install-এ rsyslog নাও থাকতে পারে, তাই এটি নিরাপদ পছন্দ। sudo systemctl enable --now fail2ban দিয়ে এটি চালু করুন এবং sudo fail2ban-client status sshd দিয়ে jail পরীক্ষা করুন। Ubuntu 24.04-এ SSH-এর জন্য fail2ban setup-এ ব্যবহৃত একই jail syntax এখানে প্রযোজ্য: Ubuntu 24.04-এ SSH-এর জন্য fail2ban setup। শুধু package source এবং ban action আলাদা।
Patching-এর গুরুত্ব port পরিবর্তনের চেয়ে বেশি
SSH port পরিবর্তন করা হলেও 4 মাস ধরে security update প্রয়োগ না করা সার্ভারের অবস্থা, port 22-এ চললেও প্রতি রাতে নিজে থেকে patch হওয়া সার্ভারের চেয়ে খারাপ। আপনি যেহেতু ইতিমধ্যে root হিসেবে session-এ আছেন, একই সময়ে unattended update চালু করুন: Rocky Linux ও AlmaLinux-এ automatic dnf update-এ timer এবং update download করা বনাম প্রয়োগ করার বিকল্প দুটির বর্ণনা রয়েছে।
FAQ
Rocky Linux-এ port পরিবর্তন করার পরে sshd start হতে ব্যর্থ হয় কেন?
প্রায় সব ক্ষেত্রেই কারণটি হলো SELinux port label অনুপস্থিত থাকা। sshd, sshd_t domain-এ confined অবস্থায় চলে, এবং policy কেবল ssh_port_t label-যুক্ত port-এ bind করার অনুমতি দেয়; ডিফল্টভাবে এটি শুধু port 22। Kernel bind প্রত্যাখ্যান করে। তাই daemon listening শুরু না করে বন্ধ হয়ে যায়, এবং journalctl -u sshd-এ সাধারণত error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.-এর মতো একটি line থাকে। নিজের port number দিয়ে sudo semanage port -a -t ssh_port_t -p tcp 2222 চালান, তারপর service restart করুন। semanage না পাওয়া গেলে আগে policycoreutils-python-utils install করুন।
SELinux permissive mode-এ থাকলেও কি semanage প্রয়োজন?
হ্যাঁ। permissive mode-এ denial record হয় এবং bind তবু অনুমোদিত হয়। তাই পরিবর্তনটি কাজ করেছে বলে মনে হয়। কিন্তু label এখনও অনুপস্থিত থাকে। কেউ setenforce 1 চালালে, অথবা /etc/selinux/config-এ SELINUX=enforcing-সহ server boot হলে, sshd ওই port-এ start হওয়া বন্ধ করবে। একটি command চালিয়ে label যোগ করলে এই সমস্যা দূর হয়। অন্যথায় কয়েক সপ্তাহ পরে কোনো স্পষ্ট কারণ ছাড়াই এটি দেখা দিতে পারে।
Port labelled এবং sshd running থাকা সত্ত্বেও connection timeout হয় কেন?
Daemon running থাকা মানে SELinux অনুমতি দিচ্ছে। তাই incoming পথে packet drop হচ্ছে। আপনার port-এর জন্য sudo firewall-cmd --list-ports পরীক্ষা করুন। --permanent rule-এর পরে firewall-cmd --reload চালিয়েছেন কি না নিশ্চিত করুন। কারণ permanent rule একা running firewall-এ প্রয়োগ হয় না। এরপর VPS-এর সামনে থাকা আলাদা network firewall-এর জন্য host-এর control panel পরীক্ষা করুন। অনেক ক্ষেত্রে এখানেই দ্বিতীয়বার traffic আটকে যায়। Operating system-এর ভেতরের কোনো তথ্য এটি দেখাবে না।
22-এর পরিবর্তে কোন port ব্যবহার করা উচিত?
1024 থেকে 65535-এর মধ্যে যেকোনো free TCP port ব্যবহার করতে পারেন। বাস্তব server-এ 2222 এবং 22222 এড়িয়ে চলুন। 22 পরীক্ষা করার পর scanner-গুলো সাধারণত এগুলোও সঙ্গে সঙ্গে পরীক্ষা করে। sudo ss -tlnp দিয়ে number-টি free কি না নিশ্চিত করুন। sudo semanage port -l দিয়ে SELinux policy আগে থেকেই এটি claim করেছে কি না পরীক্ষা করুন। পরে install করতে পারেন এমন কোনো service-এর জন্য বরাদ্দ port ব্যবহার করবেন না। মনে রাখা কঠিন এমন বড় number ব্যবহার করা যেতে পারে, কারণ ~/.ssh/config-এ একবার লিখে রাখার পরে এটি আর manually type করতে হবে না।