Docker ஏன் UFW-ஐத் தவிர்க்கிறது? தீர்வு இதோ
Docker தனது iptables விதிகளை UFW-க்கு முன்னதாகவே செயல்படுத்துவதால், நீங்கள் மூடிய போர்ட்கள் இணையத்தில் திறந்திருக்கும். இந்த சிக்கலை சரிசெய்யும் முறைகளை விரிவாகக் காண்போம்.
Docker ஏன் UFW-ஐத் தவிர்க்கிறது
Docker-ன் published container ports, UFW நிர்வகிக்கும் firewall விதிகள் வழியாகச் செல்லாததால், Docker UFW-ஐத் தவிர்க்கிறது. நீங்கள் docker run -p 8080:80-ஐ இயக்கும்போது, kernel-ன் nat table-ல் உள்ள PREROUTING chain-ல் Docker ஒரு DNAT (destination network address translation) விதியை எழுதுகிறது. அந்த விதி, packet எங்கு செல்ல வேண்டும் என்று kernel தீர்மானிக்கும் முன்பே, அதன் destination-ஐ container-ன் private address-க்கு மாற்றுகிறது. மாற்றப்பட்ட அந்த packet, Docker-ன் கட்டுப்பாட்டில் உள்ள FORWARD chain வழியாக container-க்குள் அனுப்பப்படுகிறது. UFW-ன் விதிகள் INPUT chain-ல் உள்ளன, ஆனால் packet அங்கு செல்வதே இல்லை. எனவே, ufw status default deny என்று காட்டினாலும், sudo ufw deny 8080 வெற்றிகரமாக இயங்குவதாகக் காட்டும், மேலும் port 8080 முழு இணையத்திற்கும் பதிலளிக்கும்.
இது Docker-ன் பிழையல்ல, UFW-ம் பழுதடையவில்லை. இரண்டு கருவிகளும் ஒரே kernel firewall-ஐத்தான் கையாளுகின்றன. Docker-ன் விதிகள் packet பயணத்தின் தொடக்கத்திலேயே செயல்படுவதால், UFW-விடம் அனுமதி கேட்கப்படுவதில்லை. இந்த வழிகாட்டி, இந்தத் தவிர்ப்பு எவ்வாறு நிகழ்கிறது என்பதை விளக்குவதுடன், செயல்படக்கூடிய இரண்டு தீர்வுகளையும் விவரிக்கிறது: 127.0.0.1-ல் ports-ஐ வெளியிடுதல் மற்றும் DOCKER-USER chain-ல் filtering செய்தல். உங்களுக்கு UFW புதியது என்றால், முதலில் UFW firewall அடிப்படை வழிகாட்டி மூலம் அதை அமைக்கவும், ஏனெனில் default-deny firewall தான் server-ல் உள்ள மற்ற அனைத்துக்கும் சரியான அடிப்படையாகும்.
உங்கள் சொந்த server-ல் இந்த bypass-ஐச் சரிபார்க்கவும்
UFW active நிலையில் உள்ள மற்றும் உள்வரும் traffic-க்கு default deny policy கொண்ட ஒரு VPS-ல் இருந்து தொடங்கவும். ஒரு web container-ஐ published port-உடன் இயக்கவும்:
sudo ufw status verbose
docker run -d --name web -p 8080:80 nginx:1.29-alpineufw status verbose கட்டளை Default: deny (incoming), allow (outgoing)-ஐக் காட்டுகிறது, மேலும் port 8080-க்கு எந்த விதியும் இல்லை. firewall-ன் சொந்த அறிக்கையின்படி, அந்த port மூடப்பட்டுள்ளது. இப்போது server-க்கு வெளியே உள்ள வேறொரு machine-லிருந்து சோதிக்கவும்:
curl -I http://your-vps-ip:8080/HTTP/1.1 200 OKContainer பதிலளிக்கிறது. ஒரு explicit deny விதியைச் சேர்த்து மீண்டும் சோதிக்கவும்:
sudo ufw deny 8080/tcpPort இன்னும் பதிலளிக்கிறது, ஏனெனில் deny விதி packet ஒருபோதும் செல்லாத ஒரு chain-ல் உள்ளது. UFW தோல்வியடையவில்லை. அது ஒருபோதும் கலந்தாலோசிக்கப்படவில்லை. இதனால்தான் இந்தச் சிக்கல் எளிதில் கண்டறியப்படாமல் மறைந்திருக்கிறது: எங்கும் பிழைச் செய்தி காட்டப்படுவதில்லை, deploy வெற்றிகரமாக முடிகிறது, மேலும் firewall status வெளியீடு பாதுகாப்பான server-ஐப் போலவே சரியாகத் தெரிகிறது.
செயல்முறை: PREROUTING என்பது INPUT-க்கு முன்பே இயங்குகிறது
Kernel ஒரு உள்வரும் பாக்கெட்டை ஒரு நிலையான வரிசையிலேயே கையாள்கிறது, இந்த வரிசையில்தான் முழு சிக்கலும் உள்ளது.
PREROUTINGமுதலில் இயங்குகிறது. இங்குள்ள விதிகள் பாக்கெட்டின் சேருமிடத்தை (destination) மாற்றியமைக்கலாம், Docker-ன் published port விதியும் இதைத்தான் செய்கிறது.- அடுத்ததாக routing முடிவு எடுக்கப்படுகிறது. Host-ஐ நோக்கிய பாக்கெட்
INPUTசங்கிலிக்குச் செல்கிறது. வேறொரு இயந்திரத்தை நோக்கிய பாக்கெட்FORWARDசங்கிலிக்குச் செல்கிறது. - UFW-ன் விதிகள்
INPUT-ல் உள்ளன. Docker-ன் விதிகள்FORWARD-ல் உள்ளன.
நீங்கள் இப்போது தொடங்கிய container-க்கான Docker-ன் விதியைப் பாருங்கள்:
sudo iptables -t nat -L DOCKER -nChain DOCKER (2 references)
target prot opt source destination
RETURN 0 -- 0.0.0.0/0 0.0.0.0/0
DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80DNAT வரியே முழு கதையையும் விளக்குகிறது. 8080 போர்ட்டிற்கு வரும் எந்தவொரு பாக்கெட்டும், Docker-ன் தனிப்பட்ட bridge network-ல் உள்ள container முகவரியான 172.17.0.2:80-க்கு மாற்றியமைக்கப்படுகிறது. இந்த மாற்றத்திற்குப் பிறகு, பாக்கெட் இனி host-ஐ நோக்கியதாக இருக்காது, எனவே routing முடிவு அதை FORWARD பாதைக்கு அனுப்புகிறது. அங்கு Docker ஏற்கனவே தனது சொந்த network-களுக்குள் traffic-ஐ அனுமதிக்கும் விதிகளைச் சேர்த்துள்ளது. உங்கள் deny 8080/tcp விதி, வராத ஒரு பாக்கெட்டிற்காக INPUT-ல் காத்திருக்கிறது.
Ubuntu 24.04-ல் iptables கட்டளை nftables-க்கான ஒரு front end ஆகும், ஆனால் சங்கிலி வரிசையும் அதன் விளைவும் ஒன்றுதான். UFW மற்றும் Docker ஆகிய இரண்டும் ஒரே kernel பாக்கெட் குழாயில்தான் (pipeline) எழுதுகின்றன, Docker-ன் நுழைவுப் புள்ளி முன்னதாகவே உள்ளது. இது UFW-க்கு மட்டும் உரியது அல்ல: Rocky அல்லது AlmaLinux VPS-ல் firewalld அதே குழாயின் புள்ளியில்தான் வடிகட்டுகிறது, மேலும் அதே DNAT விதியால் இது தவிர்க்கப்படுகிறது, எனவே கீழே உள்ள தீர்வுகளே இதற்கும் பொருந்தும்.
அன்றாடத் தீர்வு: 127.0.0.1-ல் ports-ஐ வெளியிடுதல்
பெரும்பாலான containers எப்போதுமே பொதுவெளியில் இருக்க வேண்டிய அவசியமில்லை. ஒரு database, reverse proxy-க்கு பின்னால் உள்ள app server, admin panel, அல்லது metrics endpoint என எதுவுமே நேரடியாக இணையத்திலிருந்து அணுகப்படக்கூடாது. இவற்றை loopback முகவரியில் மட்டும் வெளியிடவும்:
docker run -d --name web -p 127.0.0.1:8080:80 nginx:1.29-alpineஅல்லது ஒரு Compose கோப்பில்:
services:
web:
image: nginx:1.29-alpine
ports:
- "127.0.0.1:8080:80"Docker-ன் DNAT விதி இப்போது 127.0.0.1-க்கு வரும் பாக்கெட்டுகளை மட்டுமே கவனிக்கும் என்பதால் இது வேலை செய்கிறது. இணையத்திலிருந்து வரும் ஒரு பாக்கெட் ஒருபோதும் இந்த இலக்கைக் கொண்டிருக்க முடியாது, எனவே எந்த firewall விதியும் செயல்படும் முன்பே kernel அதை நிராகரித்துவிடும். இந்த port host-லிருந்து மட்டுமே அணுகக்கூடியதாக இருக்கும், வேறெங்கிருந்தும் அணுக முடியாது. binding-ஐ சரிபார்க்கவும்:
sudo ss -tlnp | grep 8080வெளியீட்டில் 0.0.0.0:8080 அல்லது [::]:8080 என்பதற்குப் பதிலாக 127.0.0.1:8080 இருக்க வேண்டும். பிறகு, வேறொரு கணினியிலிருந்து curl http://your-vps-ip:8080/ நிராகரிக்கப்படுகிறதா என்பதை உறுதிப்படுத்தவும்.
இணையத்திற்குத் தெரிய வேண்டிய சேவைகளுக்கு, 80 மற்றும் 443 ports-ஐக் கையாளும் ஒரு reverse proxy-ஐ மட்டும் இயக்கி, hostname மூலம் routing செய்யவும்; மற்ற எதையும் வெளியிட வேண்டாம். இதுவே Traefik reverse proxy வழிகாட்டி கட்டமைக்கும் முறையாகும். VPS-ல் Nextcloud போன்ற ஒரு self-hosted app அதன் proxy வழியாக மட்டுமே அணுகக்கூடியதாக இருப்பதை இது உறுதி செய்கிறது. ports: பதிவுகள் எவ்வாறு அறிவிக்கப்படுகின்றன மற்றும் Compose பணிப்பாய்வு குறித்த பிற தகவல்கள் Docker Compose அடிப்படை வழிகாட்டி-ல் உள்ளன.
அனைத்து internal container-களும் loopback-ல் இருக்கும்போது, UFW அதன் வழக்கமான பணியைச் செய்யும்: host நேரடியாக வழங்கும் ports-ஐப் பாதுகாக்கும். அந்த விதிகளின் தொகுப்பை இங்கே உருவாக்கி, பின்வரும் கட்டளைகளை வரிசையாக இயக்கவும்:
உண்மையான வடிகட்டுதல்: DOCKER-USER chain
சில நேரங்களில் ஒரு container port-ஐ நெட்வொர்க்கில் பகிரங்கமாக வைத்திருக்க வேண்டும், ஆனால் கட்டுப்படுத்த வேண்டும். உதாரணமாக, ஒரு அலுவலக முகவரிக்கு மட்டும் அணுகக்கூடிய database replica port-ஐக் கூறலாம். இதற்கு Docker DOCKER-USER chain-ஐ வழங்குகிறது. எந்தவொரு container-க்கும் செல்லும் ஒவ்வொரு packet-ம் Docker-ன் சொந்த accept விதிகளுக்கு முன்பாக DOCKER-USER வழியாகச் செல்லும். Docker இந்த chain-ல் எந்த விதிகளையும் எழுதாது. இந்த chain உங்களுக்காகவே உள்ளது, மேலும் daemon restart செய்யப்பட்டாலும் Docker இதன் உள்ளடக்கங்களை மாற்றாது.
கட்டளைக்கு முன் ஒரு முக்கியமான விஷயம்: ஒரு packet DOCKER-USER-ஐ அடையும்போது, DNAT rewrite ஏற்கனவே நடந்திருக்கும். அந்த packet-ன் destination port என்பது published port (8080) அல்ல, அது container port (80) ஆகும். எனவே --dport 8080-ஐப் பொருத்தும் விதி எதையும் கண்டறியாது. நம்பகமான வழி என்னவென்றால், client முதலில் எந்த port-ஐ அழைத்ததோ அதைச் சரிபார்ப்பதுதான்; இதை kernel-ன் connection tracker நினைவில் வைத்திருக்கும்:
sudo iptables -I DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 8080 --ctdir ORIGINAL ! -s 10.0.0.10 -j DROPஇதை இவ்வாறு வாசிக்கவும்: eth0 வழியாக வந்த மற்றும் அதன் அசல் destination port 8080 ஆக இருந்த connection-க்குச் சொந்தமான packet-களில், 10.0.0.10-லிருந்து வராத அனைத்தையும் நிராகரிக்கவும் (drop). --ctdir ORIGINAL match, இந்த விதியை client-to-container திசைக்கு மட்டும் கட்டுப்படுத்துகிறது, எனவே பதில் packet-கள் (reply packets) தவறுதலாக இதில் சிக்காது. eth0-க்கு பதிலாக உங்கள் public interface-ஐ இடவும்; ip route | grep default அதை வரையறுக்கிறது. இதை முன்போலவே சோதிக்கவும்: அனுமதிக்கப்பட்ட முகவரியிலிருந்து curl வெற்றிகரமாகச் செயல்படும், மற்ற இடங்களிலிருந்து connection time out ஆகும். அந்தத் தாமதம் (hang), பின்னால் சேவை இல்லாத port-ஐ விட, DROP விதி சரியாகச் செயல்படுவதற்கான அறிகுறியாகும். மேலும் நிராகரிக்கப்பட்ட connection-க்கும் time out ஆகும் connection-க்கும் உள்ள வேறுபாடு, ஒரு port வடிகட்டப்பட்டுள்ளதா அல்லது சேவை இயங்கவில்லையா என்பதைக் கண்டறிய மிக வேகமான வழியாகும்.
iptables கட்டளை மூலம் சேர்க்கப்படும் விதிகள் reboot-க்குப் பிறகு மறைந்துவிடும். UFW ஏற்கனவே இந்த firewall-ஐ நிர்வகிப்பதால், அவற்றை நிரந்தரமாகச் சேமிக்க /etc/ufw/after.rules சரியான இடமாகும். கோப்பின் இறுதியில் பின்வரும் தொகுப்பைச் சேர்க்கவும்:
*filter
:DOCKER-USER - [0:0]
-A DOCKER-USER -i eth0 -p tcp -m conntrack --ctorigdstport 8080 --ctdir ORIGINAL ! -s 10.0.0.10 -j DROP
COMMITபிறகு sudo ufw reload-ஐ இயக்கவும். ஒவ்வொரு முறை reload செய்யும்போதும் மற்றும் ஒவ்வொரு boot-ன் போதும் UFW இந்தக் கோப்பை மீண்டும் இயக்கும். எனவே உங்கள் container வடிகட்டுதல் இப்போது உங்கள் firewall-ன் மற்ற பகுதிகளுடன் ஒரே இடத்தில் இருக்கும், மேலும் இது reboot மற்றும் Docker upgrade ஆகிய இரண்டையும் தாங்கி நிற்கும்.
Docker-ன் iptables ஒருங்கிணைப்பை ஏன் முடக்கக்கூடாது
இந்தச் சிக்கலுக்கு பழைய தீர்வுகளில் { "iptables": false }-ஐ /etc/docker/daemon.json-ல் அமைக்க பரிந்துரைக்கப்படுகிறது. அதைச் செய்ய வேண்டாம். Docker-ன் firewall விதிகள் ports-ஐ வெளியிடுவதைத் தாண்டி பல பணிகளைச் செய்கின்றன. Masquerade விதிதான் containers-க்கு host-ன் முகவரி வழியாக இணைய அணுகலை வழங்குகிறது; எனவே, இந்த ஒருங்கிணைப்பு முடக்கப்பட்டால், containers-ஆல் images-ஐப் பதிவிறக்கவோ, package mirrors-ஐ அணுகவோ அல்லது எந்தவொரு external API (application programming interface)-ஐ அழைக்கவோ முடியாது. DNAT விதிகள்தான் -p சரியாகச் செயல்படக் காரணமாகின்றன, எனவே அவற்றை முடக்கினால் published ports முற்றிலும் வேலை செய்யாது. தனித்தனி Compose networks-ஐப் பிரித்து வைக்கும் isolation விதிகளும் நீங்கிவிடும். நீங்கள் இந்த bypass-ஐச் சரிசெய்ய முயலும்போது container networking-ஐச் சிதைத்துவிடுவீர்கள், மேலும் அந்த விதிகள் அனைத்தையும் நீங்களே கைமுறையாக எழுதிப் பராமரிக்க வேண்டியிருக்கும். Docker-ன் சொந்த ஆவணங்களே, இதைச் செய்யத் திட்டமிடுபவர்களுக்கான அமைப்பு என்றுதான் இதைக் குறிப்பிடுகிறது. DOCKER-USER chain இருப்பதன் நோக்கமே, யாரும் இந்த மாற்றத்தைச் செய்ய வேண்டிய அவசியம் இருக்கக்கூடாது என்பதற்காகத்தான்.
IPv6-ல் இதே சிக்கல்
முதலில் IPv6-ல் published port எவ்வாறு உள்ளது என்பதைச் சரிபார்க்கவும்:
sudo ss -tlnp | grep 8080Docker Engine 27 முதல், Docker இயல்பாகவே ip6tables-ஐ நிர்வகிக்கிறது. IPv6 வசதி கொண்ட Docker network-ல், ஒரு published port-க்கு IPv6 tables-லும் அதே DNAT செயல்முறைதான் நடக்கும். எனவே, அங்கும் அதே bypass சிக்கல் உள்ளது, அதே தீர்வும் பொருந்தும்: DOCKER-USER chain ip6tables-லும் உள்ளது. எனவே, உங்கள் விதியை sudo ip6tables -I DOCKER-USER ... மூலம் பிரதிபலித்து, உங்கள் server-ன் பொது IPv6 முகவரிக்கு எதிராக curl -6 http://[2001:db8:2a::1]:8080/ போன்ற கட்டளையைப் பயன்படுத்தி வெளியிலிருந்து சோதிக்கவும்.
IPv6 இல்லாத network-ல், IPv6 clients-ஐ docker-proxy கையாளும். இது [::]:8080-ல் listening செய்யும் ஒரு சாதாரண user-space process ஆகும்; இது traffic-ஐ IPv4 வழியாக container-க்கு forward செய்யும். Host process-க்கு செல்லும் traffic INPUT வழியாகவே செல்லும், எனவே UFW அந்தப் பாதையை வடிகட்ட முடியும். ஆனால், UFW IPv6-ஐ நிர்வகிக்கும்போது மட்டுமே இது சாத்தியம். அது நிர்வகிக்கப்படுகிறதா என்பதையும், VPS-ல் IPv6 இடைவெளி உருவாகும் பிற வழிகளையும் UFW மற்றும் IPv6 வழிகாட்டி-ல் காணலாம்.
Loopback-ல் publish செய்வது இந்தச் சிக்கலை முழுமையாகத் தவிர்க்கிறது: -p 127.0.0.1:8080:80 IPv4 loopback-ஐ மட்டுமே bind செய்யும். எனவே, IPv6 listener இருக்காது, எந்த stack வழியாகவும் வெளியிலிருந்து எதையும் அணுக முடியாது.
நிலையான வடிவமைப்பு
- அனைத்து internal port-களையும்
127.0.0.1-ல் publish செய்யவும், இதன் மூலம் அவை எக்காரணம் கொண்டும் நேரடியாக வெளிப்படாது. - பொதுவான அணுகல் பக்கத்தை 80 மற்றும் 443 ports-ஐக் கையாளும் ஒரு reverse proxy-க்கு வழங்கவும்.
- Host-க்கான UFW default deny விதியை அப்படியே வைத்திருக்கவும்; SSH மற்றும் proxy ports-க்கு மட்டும் அனுமதி அளிக்கவும்.
- உண்மையாகவே பொதுமக்களுக்குத் தேவைப்படும் container ports-ஐ
DOCKER-USER-ல் வடிகட்டவும்; இவை original destination port-உடன் ஒத்துப்போக வேண்டும் மற்றும்/etc/ufw/after.rules-ல் நிலைநிறுத்தப்பட வேண்டும். - Docker-ன் iptables integration-ஐ இயக்கத்திலேயே வைத்திருக்கவும்.
ஒருமுறை அமைத்துவிட்டால், இது குழப்பங்களைத் தவிர்க்கும்: ufw status host-ஐ விவரிக்கிறது, DOCKER-USER container-களை விவரிக்கிறது. தற்செயலாக எதுவும் publish செய்யப்படாது, நீங்கள் அடுத்து டைப் செய்யும் docker run -p நீங்கள் எதை வெளிப்படுத்த விரும்பினீர்களோ அதை மட்டுமே வெளிப்படுத்தும்.
FAQ
UFW மூலம் port தடுக்கப்பட்டிருந்தாலும், Docker container-ஐ என்னால் ஏன் அணுக முடிகிறது?
ஏனெனில், Docker அந்த port-ஐ PREROUTING chain-ல் ஒரு DNAT விதியின் மூலம் வெளியிடுகிறது. எந்தவொரு வடிகட்டுதலும் (filtering) நடப்பதற்கு முன்பே, இது packet-ன் இலக்கை container-ன் முகவரிக்கு மாற்றிவிடுகிறது. அதன் பிறகு அந்த packet FORWARD பாதையில் பயணிக்கிறது. UFW-ன் விதிகள் INPUT-ல் உள்ளன; அந்த chain-க்குள் packet நுழைவதே இல்லை. இதனால் firewall-ன் ஆலோசனை பெறப்படுவதில்லை, எனவே அதன் deny விதிகள் வெளியிடப்பட்ட container port-களில் எந்த தாக்கத்தையும் ஏற்படுத்துவதில்லை.
Docker வெளியிடும் port-களை UFW மூலம் தடுப்பது எப்படி?
UFW-ன் விதிகள் தவறான chain-ல் இருப்பதால், அதை நேரடியாகச் செய்ய முடியாது. ஒன்று, அந்த port-ஐ 127.0.0.1:8080:80 என publish செய்து host-ஆல் மட்டுமே அணுகும்படி மாற்ற வேண்டும். அல்லது, conntrack மூலம் அசல் destination port-ஐக் கண்டறியும் iptables விதியைப் பயன்படுத்தி DOCKER-USER chain-ல் வடிகட்ட வேண்டும். அந்த விதியை /etc/ufw/after.rules-ல் சேமித்து வைத்தால் மட்டுமே, அது reboot மற்றும் ufw reload-க்குப் பிறகும் நிலைத்திருக்கும்.
Docker-ன் daemon.json கோப்பில் "iptables": false என்று அமைக்க வேண்டுமா?
கூடாது. அந்த அமைப்பு Docker-ன் அனைத்து firewall மற்றும் NAT விதிகளையும் நீக்கிவிடும், இது bypass சிக்கலை விட அதிக பாதிப்புகளை ஏற்படுத்தும். masquerade விதி நீக்கப்படுவதால் container-களுக்கு இணைய அணுகல் கிடைக்காது, DNAT விதிகள் நீக்கப்படுவதால் வெளியிடப்பட்ட port-கள் வேலை செய்யாது. அதற்குப் பதிலாக loopback publishing மற்றும் DOCKER-USER chain-ஐப் பயன்படுத்தவும்; இவை container networking-ஐ பாதிக்காமல் தேவையற்ற அணுகலைத் தடுக்கும்.
IPv6-லும் Docker UFW-ஐத் தவிர்க்கிறதா?
Docker Engine 27 மற்றும் அதற்குப் பிந்தைய பதிப்புகளில், ip6tables மேலாண்மை இயல்பாகவே செயல்பாட்டில் உள்ளது. எனவே, IPv6 வசதி கொண்ட Docker network-ல் வெளியிடப்படும் port, IPv4-ஐப் போலவே UFW-ஐத் தவிர்த்து மாற்றியமைக்கப்படுகிறது. இதற்கு ip6tables-ஐப் பயன்படுத்தி DOCKER-USER விதியை உருவாக்க வேண்டும். IPv6 இல்லாத network-களில், docker-proxy செயல்முறை [::]-ல் கேட்கிறது (listen). அந்த traffic INPUT வழியாகச் செல்வதால், UFW IPv6-ஐ நிர்வகித்தால் அதை வடிகட்ட முடியும். 127.0.0.1-ல் publish செய்வது இந்த இரண்டு சிக்கல்களையும் தவிர்க்கும், ஏனெனில் அங்கு IPv6-ல் எதுவும் listen செய்யாது.