CGNAT के पीछे port forwarding कैसे करें: VPS तरीका
CGNAT के कारण public IP न होने पर परेशान हैं? एक सस्ते VPS पर frp का उपयोग करके reverse tunnel बनाएं और अपने home server को सुरक्षित रूप से इंटरनेट पर एक्सेस करें।
CGNAT के पीछे port forwarding काम क्यों नहीं करता है
CGNAT (carrier-grade network address translation) के पीछे आपके router का WAN address अन्य subscribers के साथ साझा किया जाता है। इसलिए, आपके पास कोई public IP नहीं होता है और forward करने के लिए कोई port उपलब्ध नहीं होता है। एक reverse tunnel इस समस्या का समाधान करती है: एक सस्ता VPS public IP रखता है, आपका home box VPS से connection बनाता है, और inbound requests उसी connection के माध्यम से वापस आते हैं जिसे home box ने पहले ही खोल रखा है। आप अपना मौजूदा hardware इस्तेमाल करना जारी रखते हैं। आप केवल वह एक चीज़ किराए पर लेते हैं जो आपका ISP आपको नहीं देगा, और वह है एक routable address।
नीचे दिए गए प्रत्येक command के साथ उस machine का नाम लिखा है जिस पर उसे चलाना है। इसके लिए दो machines की आवश्यकता है: एक public IP वाला VPS, और वह home box जिस पर वह service चल रही है जिसे आप access करना चाहते हैं।
यह कैसे पता करें कि आप वास्तव में CGNAT के पीछे हैं
अपने राउटर का एडमिन पेज खोलें और वहां दिखाई देने वाला WAN एड्रेस देखें। इसके बाद इंटरनेट पर जांचें कि उसे आपका कौन सा एड्रेस दिखाई दे रहा है।
# on the home box
curl -4 -s https://ifconfig.me; echoयदि दोनों एड्रेस मेल खाते हैं, तो आपके पास एक पब्लिक IP है और आपको इस प्रक्रिया की आवश्यकता नहीं है। पोर्ट फॉरवर्ड करें और आगे पढ़ना बंद करें। यदि राउटर का WAN एड्रेस 100.64.0.0/10 के भीतर है, तो आप CGNAT के पीछे हैं। वह ब्लॉक RFC 6598 शेयर्ड एड्रेस स्पेस है, जिसे विशेष रूप से इसी उपयोग के लिए आरक्षित किया गया है। कुछ ISP WAN साइड पर 10.0.0.0/8 का उपयोग करते हैं, जो अलग नाम के साथ वही स्थिति है।
कुछ भी किराए पर लेने से पहले एक चीज की जांच करें। कई CGNAT ISP एक वास्तविक IPv6 प्रीफिक्स देते हैं, और यदि आपके होम बॉक्स के पास ग्लोबल IPv6 एड्रेस है, तो आप उस एड्रेस पर फायरवॉल खोल सकते हैं और टनल की आवश्यकता को पूरी तरह से छोड़ सकते हैं। यह तब काम करना बंद कर देता है जब कोई विजिटर केवल IPv4 नेटवर्क पर होता है, यही कारण है कि अधिकांश लोग अंततः यहाँ पहुँचते हैं।
VPS reverse tunnel कैसे काम करता है, अंदर से बाहर की ओर dial करना
CGNAT और सामान्य home routers दोनों ही unsolicited inbound connections को block करते हैं। Corporate firewalls भी ऐसा ही करते हैं। इनमें से कोई भी outbound connections को block नहीं करता, क्योंकि हर browser और हर update client दिन भर यही करता है। एक NAT device जो outbound TCP connection देखता है, वह उसके लिए एक mapping बनाता है और फिर उस connection पर return traffic की अनुमति देता है। बाहर से कोई भी आपके home box पर connection शुरू नहीं कर सकता। इसलिए home box इसे शुरू करता है, और tunnel उसी connection के माध्यम से traffic को दूसरी दिशा में वापस ले जाती है।
यही पूरी प्रक्रिया है। Home box एक port पर VPS से बाहर की ओर connect होता है और connection को open रखता है। VPS public requests को स्वीकार करता है और उन्हें उस मौजूदा connection के माध्यम से नीचे भेज देता है। कोई भी कभी भी आपके home IP address तक पहुँचने की कोशिश नहीं करता, इसलिए किसी को ऐसा करने की आवश्यकता भी नहीं होती।
इसके दो परिणाम निकलते हैं, और दोनों उपयोगी हैं। आपका DNS record VPS की ओर इशारा करता है, आपके घर की ओर कभी नहीं। और आपका public address अब VPS का address है, इसलिए IP lookup से कोई observer जो कुछ भी पता लगाता है, वह आपके home line के बजाय एक rented server के बारे में होता है।
इसे बनाने के तीन तरीके
ssh -R: दोनों सिरों पर पहले से इंस्टॉल होता है, और एक सर्विस या अस्थायी डेमो के लिए सही है। इसमें कोई डैशबोर्ड नहीं मिलता और न ही इसमें कोई प्रभावी रिकनेक्शन लॉजिक है।- frp: एक छोटा Go सर्वर (
frps) और एक मेल खाता क्लाइंट (frpc)। यह एक ही होस्टनेम के पीछे कई सर्विसेज वाले स्थायी सेटअप के लिए सही है। यह गाइड का मुख्य हिस्सा है। - एक मेश VPN: Tailscale, या आपका अपना WireGuard सर्वर। यह तब सही है जब आप चाहते हैं कि आपके अपने डिवाइस निजी तौर पर एक-दूसरे से जुड़ें, न कि किसी चीज़ को सार्वजनिक इंटरनेट पर प्रकाशित करना हो।
यदि आपका लक्ष्य अपने नियंत्रित डिवाइस से निजी एक्सेस प्राप्त करना है, तो मेश चुनें। Tailscale Serve और Funnel एक टेलनेट (tailnet) से बाहर प्रकाशित करने के बारे में जानकारी देता है, और उसी VPS पर एक सेल्फ-होस्टेड WireGuard VPN आपको बिना किसी थर्ड-पार्टी कोऑर्डिनेशन सर्वर के वही सेटअप प्रदान करता है। उनमें से एक पढ़ें और इस पेज के बाकी हिस्से को छोड़ दें। नीचे दी गई हर चीज़ यह मानकर चलती है कि आप एक सार्वजनिक HTTPS होस्टनेम चाहते हैं जिसे कोई भी लोड कर सके।
संक्षिप्त संस्करण: ssh -R एक सर्विस के लिए
मान लीजिए कि आपका होम बॉक्स 127.0.0.1:3000 पर एक ऐप चलाता है और आपके पास VPS का SSH एक्सेस पहले से मौजूद है।
# on the home box
ssh -N \
-o ExitOnForwardFailure=yes \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-R 127.0.0.1:8080:127.0.0.1:3000 \
tunnel@vps.example.com-R 127.0.0.1:8080:127.0.0.1:3000 VPS के sshd को उसके अपने 127.0.0.1:8080 पर सुनने (listen) और वहां आने वाले किसी भी ट्रैफिक को होम बॉक्स के 127.0.0.1:3000 पर भेजने का निर्देश देता है। -N का अर्थ है कि कोई शेल (shell) रन न करें। दो ServerAlive विकल्प ssh को लगभग नब्बे सेकंड में डेड लिंक का पता लगाने में मदद करते हैं, ताकि वह ऐसी कनेक्शन पर न अटके जो अब मौजूद नहीं है।
अब वह हिस्सा जो सबको भ्रमित करता है। वह लिसनर लूपबैक (loopback) पर है, इसलिए कहीं और से curl http://vps.example.com:8080 विफल हो जाता है। sshd GatewayPorts no के साथ आता है, जिसका अर्थ है कि रिमोट फॉरवर्ड केवल लूपबैक इंटरफ़ेस से जुड़ता है। इसे GatewayPorts yes सेट करके ठीक करने का प्रयास न करें। फॉरवर्ड को लूपबैक पर ही रहने दें और इसके सामने nginx लगाएँ, ठीक वैसे ही जैसे नीचे frp सेटअप में किया गया है। इस तरह पब्लिक पोर्ट 443 सर्टिफिकेट के साथ रहता है और टनल पोर्ट कभी इंटरनेट के सामने नहीं आता। यदि आप सुनिश्चित नहीं हैं कि वर्तमान में कौन सा पोर्ट किस इंटरफ़ेस पर लिसन कर रहा है, तो Linux पर पोर्ट और लिसनर्स का संक्षिप्त विवरण पढ़ना दस मिनट का सार्थक निवेश होगा।
यदि VPS पर पोर्ट पहले से ही किसी और द्वारा लिया गया है, तो ssh यह प्रिंट करता है, और ExitOnForwardFailure=yes इसे बिना काम करने वाली टनल के कनेक्ट होने के बजाय रुकने (give up) के लिए मजबूर करता है:
Warning: remote port forwarding failed for listen port 8080इसका सामान्य कारण पिछला सत्र (session) है जो sshd के नोटिस किए बिना समाप्त हो गया। VPS की /etc/ssh/sshd_config में ClientAliveInterval 30 और ClientAliveCountMax 3 सेट करें ताकि डेड सत्र समाप्त हो जाएँ और पोर्ट रिलीज़ हो जाए। पूरे कमांड को Restart=always और एक समर्पित की (key) के साथ systemd यूनिट में रैप करें, या autossh का उपयोग करें। एक से अधिक सर्विस के लिए, यहाँ रुकें और frp का उपयोग करें।
VPS पर frp इंस्टॉल करें, एक विशिष्ट टैग के साथ
frp एक static Go binary के रूप में उपलब्ध है और यह Ubuntu या Debian archives में शामिल नहीं है, इसलिए आप इसे release से डाउनलोड करें और स्वयं verify करें। version को pin करें। v0.52.0 के बाद configuration format बदल गया है और option के नाम भी बदल दिए गए हैं, इसलिए पुराने tutorial में ऐसी keys हो सकती हैं जिन्हें आपका binary न पहचाने। यह गाइड v0.71.0 का उपयोग करती है, जिसे 14 August 2026 को जारी किया गया था।
# on the VPS
FRP_VERSION=0.71.0
ARCH=amd64 # use arm64 if `uname -m` prints aarch64
cd /tmp
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
curl -fsSLO "https://github.com/fatedier/frp/releases/download/v${FRP_VERSION}/frp_sha256_checksums.txt"
sha256sum --check --ignore-missing frp_sha256_checksums.txtsha256sum को ठीक एक लाइन प्रिंट करनी चाहिए:
frp_0.71.0_linux_amd64.tar.gz: OK--ignore-missing की आवश्यकता इसलिए है क्योंकि checksum file में सभी अठारह release assets शामिल हैं और आपने उनमें से केवल एक डाउनलोड किया है। उस flag के बिना, sha256sum बाकी सत्रह फाइलों को missing बताएगा और non-zero exit code देगा, जो verification विफल होने जैसा प्रतीत होता है जबकि वास्तव में सब कुछ सही है।
# on the VPS
tar xzf "frp_${FRP_VERSION}_linux_${ARCH}.tar.gz"
sudo install -m 755 "frp_${FRP_VERSION}_linux_${ARCH}/frps" /usr/local/bin/frps
sudo useradd --system --no-create-home --shell /usr/sbin/nologin frp
sudo install -d -m 750 -o root -g frp /etc/frp
frps --versionfrps --version, 0.71.0 प्रिंट करता है। केवल frps को VPS पर रखें। frpc को home box पर रखें। हर जगह दोनों binaries इंस्टॉल करने के कारण ही लोग गलती से घर पर tunnel server चला बैठते हैं।
VPS कॉन्फ़िगरेशन: टोकन, अनिवार्य TLS, और लूपबैक लिसनर्स
सबसे पहले एक टोकन जनरेट करें। यही वह एकमात्र सुरक्षा है जो आपके टनल और VPS को पोर्ट-स्कैन करने वाले किसी भी व्यक्ति के बीच मौजूद है।
# on the VPS
openssl rand -base64 32उस मान को /etc/frp/frps.toml में लिखें:
bindAddr = "0.0.0.0"
bindPort = 7000
# Every listener frp creates for a proxy, including the HTTP vhost, stays on loopback.
proxyBindAddr = "127.0.0.1"
vhostHTTPPort = 8080
auth.method = "token"
auth.token = "PASTE_THE_OPENSSL_OUTPUT_HERE"
transport.tls.force = true
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "PASTE_A_SECOND_SECRET_HERE"
log.level = "info"इनमें से चार लाइनें सुरक्षा का काम करती हैं, इसलिए उन्हें एक-एक करके समझें।
auth.token का मिलान क्लाइंट पर मौजूद auth.token से होना चाहिए। इसके बिना, frps किसी भी ऐसे क्लाइंट को स्वीकार कर लेगा जिसे पोर्ट 7000 मिल जाता है, और वह क्लाइंट आपके VPS और आपके सर्टिफिकेट के माध्यम से कुछ भी पब्लिश कर सकता है।
transport.tls.force = true किसी भी ऐसे कंट्रोल कनेक्शन को अस्वीकार कर देता है जो TLS (ट्रांसपोर्ट लेयर सिक्योरिटी) नहीं है। v0.50.0 के बाद से क्लाइंट्स में TLS डिफ़ॉल्ट रूप से इनेबल होता है, इसलिए व्यावहारिक रूप से इसका कोई अतिरिक्त खर्च नहीं है और यह उस स्थिति को रोकता है जहाँ कोई पुराना या मैन्युअल रूप से बनाया गया क्लाइंट बिना बताए क्लियर टेक्स्ट में कनेक्ट हो जाए।
proxyBindAddr = "127.0.0.1" वह लाइन है जिसे अधिकांश गाइड छोड़ देते हैं, और यही कारण है कि इस सेटअप को चलते हुए छोड़ना सुरक्षित है। यह frp द्वारा प्रॉक्सी की ओर से खोले गए प्रत्येक लिसनर को, चाहे वह HTTP vhost हो या कोई remotePort जिसे क्लाइंट मांगता है, लूपबैक इंटरफ़ेस पर ले जाता है। इंटरनेट इन लिसनर्स तक बिल्कुल नहीं पहुँच सकता। एकमात्र सार्वजनिक द्वार पोर्ट 443 पर nginx है, जिसे आप कॉन्फ़िगर और नियंत्रित करते हैं।
webServer.addr = "127.0.0.1" डैशबोर्ड को सार्वजनिक इंटरफ़ेस से दूर रखता है। डैशबोर्ड आपकी निजी सेवाओं और उनके ट्रैफ़िक का एक पूरा नक्शा है, जो केवल एक HTTP बेसिक ऑथ पासवर्ड द्वारा सुरक्षित है, इसलिए इसे 0.0.0.0 पर नहीं होना चाहिए।
ओनरशिप सेट करें ताकि टोकन को कोई भी पढ़ न सके, फिर कुछ भी शुरू करने से पहले सिंटैक्स की जाँच करें:
# on the VPS
sudo chown root:frp /etc/frp/frps.toml
sudo chmod 640 /etc/frp/frps.toml
sudo -u frp frps verify -c /etc/frp/frps.tomlएक वैध फ़ाइल यह आउटपुट देगी:
frps: the configuration file /etc/frp/frps.toml syntax is okएक फ़ॉर्मेट नोट जो आपका एक घंटा बचाएगा। frp फ़ाइल एक्सटेंशन से अपना पार्सर चुनता है, और यह .toml, .yaml, .yml और .json को पहचानता है। पुरानी .ini फ़ाइलें अभी भी लेगेसी कन्वर्जन पाथ के माध्यम से लोड होती हैं, लेकिन INI अब डेप्रिकेटेड (deprecated) है और नए विकल्प केवल TOML के लिए डॉक्यूमेंटेड हैं। यदि कोई ट्यूटोरियल आपको [common] सेक्शन और server_addr = x.x.x.x दिखाता है, तो वह v0.52.0 से पुराना है और उसके की-नेम (key names) आपके द्वारा इंस्टॉल की गई बाइनरी से मेल नहीं खाएंगे।
frps को एक unprivileged service के रूप में चलाएं
bindPort 7000 है और vhostHTTPPort 8080 है। दोनों 1024 से ऊपर हैं, इसलिए frps को कभी भी root की आवश्यकता नहीं होती और न ही इसे CAP_NET_BIND_SERVICE की आवश्यकता होती है। यही कारण है कि vhost को port 80 पर न रखें और इसके बजाय Nginx को वह कार्य संभालने दें।
/etc/systemd/system/frps.service लिखें:
[Unit]
Description=frp reverse tunnel server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
Restart=on-failure
RestartSec=5s
LimitNOFILE=65535
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
[Install]
WantedBy=multi-user.target# on the VPS
sudo systemctl daemon-reload
sudo systemctl enable --now frps
sudo journalctl -u frps -n 20 --no-pagerलॉग में दोनों listeners दिखने चाहिए, और ports की तुलना में addresses अधिक महत्वपूर्ण हैं:
frps tcp listen on 0.0.0.0:7000
http service listen on 127.0.0.1:8080ProtectSystem=strict इस service के लिए पूरे filesystem को read-only बना देता है। frps इसे स्वीकार करता है क्योंकि इसका लॉग डिफ़ॉल्ट रूप से standard output पर जाता है और journald उसे capture कर लेता है। यदि आप log.to को किसी file path पर सेट करते हैं, तो service उसे लिखने में विफल हो जाएगी जब तक कि आप एक matching ReadWritePaths= लाइन न जोड़ें, इसलिए डिफ़ॉल्ट सेटिंग को न बदलें।
Firewall: एक port खोलें, range नहीं
# on the VPS
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 7000/tcp
sudo ufw enable
sudo ufw status numberedकुल चार rules हैं, जिनमें से एक केवल certificate renewal के लिए है। 22, SSH के लिए है। 80, 443 पर redirect करता है और ACME (automatic certificate management environment) challenge का उत्तर देता है। 443 सभी tunnelled apps को serve करता है। 7000, frp control port है, और यह एकमात्र port है जिसे client को access करने की आवश्यकता होती है।
जो guides आपको sudo ufw allow 20000:30000/tcp जैसी range खोलने के लिए कहती हैं, वे उस दूसरे design का वर्णन कर रही हैं, जहाँ प्रत्येक service अपना स्वयं का public TCP port लेती है। आपको यहाँ इसकी आवश्यकता नहीं है, क्योंकि सब कुछ 443 पर आता है और frp इसे hostname के आधार पर route करता है। यदि आपको बाद में किसी एक वास्तविक public TCP port की आवश्यकता हो, तो proxyBindAddr को वापस 0.0.0.0 पर सेट करें और limits जोड़ें ताकि client केवल आपके द्वारा बताए गए ports ही ले सके:
allowPorts = [
{ start = 20000, end = 20010 }
]
maxPortsPerClient = 5अधिकांश providers server के अंदर मौजूद ufw से अलग, control panel में एक network firewall भी चलाते हैं। यदि कोई rule sudo ufw status में सही दिखता है लेकिन फिर भी timeout हो जाता है, तो वह आमतौर पर वहीं से block हो रहा होता है। VPS को वास्तव में जिन ufw rules की आवश्यकता होती है उस default-deny setup के बारे में बताता है जिसे यह section आधार मानकर चलता है।
VPS पर एक वास्तविक certificate के साथ HTTPS terminate करें
home.example.com के लिए एक A record को VPS के public IP पर point करें। इसे अपने घर के IP पर point न करें। आपके घर का कोई public address नहीं है, और यही वह समस्या है जिसे आप हल कर रहे हैं।
# on the VPS
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginxसबसे पहले एक plain port 80 block के साथ /etc/nginx/sites-available/home.example.com बनाएँ, ताकि certbot के पास काम करने के लिए एक मेल खाता हुआ server_name उपलब्ध हो:
server {
listen 80;
listen [::]:80;
server_name home.example.com;
location / { return 404; }
}# on the VPS
sudo ln -s /etc/nginx/sites-available/home.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot certonly --nginx -d home.example.comजब files parse हो जाती हैं, तो nginx -t, nginx: configuration file /etc/nginx/nginx.conf test is successful प्रिंट करता है। हर reload से पहले इसे चलाएँ। यदि reload विफल हो जाता है, तो nginx पुरानी configuration को ही चलाता रहता है, इसलिए एक त्रुटिपूर्ण edit ऐसा लग सकता है जैसे उसने कुछ किया ही न हो।
WebSocket upgrades के लिए http level पर एक map की आवश्यकता होती है। इसे /etc/nginx/conf.d/upgrade.conf में डालें:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}अब site file को वास्तविक file से बदलें:
server {
listen 80;
listen [::]:80;
server_name home.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name home.example.com;
ssl_certificate /etc/letsencrypt/live/home.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/home.example.com/privkey.pem;
client_max_body_size 512m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
}
}यहाँ proxy_set_header Host $host; वैकल्पिक नहीं है। frp का HTTP vhost, Host header के आधार पर routing करता है, और इसे client config में मौजूद customDomains list के साथ match करता है। यदि आप उस header को हटा देते हैं, तो nginx Host: 127.0.0.1 भेजेगा, frp को उस नाम के लिए कोई proxy नहीं मिलेगा, और आपके visitor को app के page के बजाय frp की ओर से एक 404 error मिलेगा। nginx reverse proxy block की हर पंक्ति का विवरण में बताया गया है कि अन्य headers क्या काम करते हैं।
# on the VPS
sudo nginx -t && sudo systemctl reload nginx
sudo certbot renew --dry-runDry run यह सुनिश्चित करता है कि नब्बे दिनों बाद, जब आप निगरानी नहीं कर रहे होंगे, तब भी renewal काम करेगा। इसके लिए port 80 का reachable होना आवश्यक है, इसीलिए वह ufw rule वहाँ दिया गया है।
होम साइड: एक unprivileged service के रूप में frpc
अपने home box पर frpc को बिल्कुल उसी तरह install करें जैसे आपने frps को किया था, वही version और वही checksum step अपनाएं। इसके बाद, वही frp user और /etc/frp directory बनाएँ। /etc/frp/frpc.toml लिखें:
serverAddr = "vps.example.com"
serverPort = 7000
auth.method = "token"
auth.token = "PASTE_THE_SAME_TOKEN_HERE"
transport.tls.enable = true
loginFailExit = false
proxies = [
{ name = "home-app", type = "http", localIP = "127.0.0.1", localPort = 3000, customDomains = ["home.example.com"] }
]इस file में key का क्रम मायने रखता है, और यह केवल दिखावे के लिए नहीं है। TOML किसी table header के बाद आने वाली हर key को उसी table का हिस्सा मान लेता है। इसलिए, यदि आप serverAddr जैसी top-level setting को किसी proxy table header के नीचे लिखते हैं, तो वह चुपचाप एक proxy setting बन जाती है जिसे frp अनदेखा कर देता है। proxy list को inline array के रूप में लिखने से, जैसा कि ऊपर दिखाया गया है, यह समस्या नहीं होती: हर top-level key स्पष्ट रूप से top-level ही रहती है।
type = "http" इस proxy को अपना public TCP port लेने के बजाय vhost listener के माध्यम से route करता है, यही कारण है कि firewall पर केवल चार rules ही रखने पड़े। customDomains में वह hostname होना चाहिए जिसे nginx Host header में forward करता है, इसलिए यह home.example.com ही होगा, न कि VPS का IP address।
loginFailExit = false जितना दिखता है उससे कहीं अधिक महत्वपूर्ण है। इसका default मान true है, जिसके कारण यदि पहला login प्रयास विफल हो जाता है, तो frpc बंद हो जाता है। ऐसे home box पर जो ISP link के सक्रिय होने से पहले ही boot हो जाता है, यह एक ऐसी service है जो तब तक मृत रहती है जब तक आप उस पर ध्यान न दें। इसे false पर set करें ताकि frpc तब तक retry करता रहे जब तक VPS जवाब न दे दे।
/etc/systemd/system/frpc.service लिखें:
[Unit]
Description=frp reverse tunnel client
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=frp
Group=frp
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
Restart=always
RestartSec=10s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target# on the home box
sudo chown root:frp /etc/frp/frpc.toml
sudo chmod 640 /etc/frp/frpc.toml
sudo -u frp frpc verify -c /etc/frp/frpc.toml
sudo systemctl daemon-reload
sudo systemctl enable --now frpc
sudo journalctl -u frpc -n 20 --no-pagerconnect होने वाला client एक run id log करता है:
login to server success, get run id [3a1f9c2b7d4e5f60]browser में https://home.example.com खोलें और आपको वह app मिल जाना चाहिए जो घर पर 127.0.0.1:3000 पर चल रहा है। client पर Restart=always जानबूझकर रखा गया है: home connections बीच में टूट सकते हैं, और service को आपके हस्तक्षेप के बिना वापस आ जाना चाहिए।
डैशबोर्ड को पब्लिक इंटरफेस से दूर रखें
webServer.addr = "127.0.0.1" के साथ डैशबोर्ड केवल VPS पर ही रिस्पॉन्स देता है। पोर्ट खोलने के बजाय अपने लैपटॉप से लोकल फॉरवर्ड का उपयोग करके इसे एक्सेस करें:
# on your laptop
ssh -N -L 7500:127.0.0.1:7500 you@vps.example.comhttp://127.0.0.1:7500 खोलें और frps.toml से प्राप्त webServer.user और webServer.password के साथ साइन इन करें। यह पेज प्रत्येक कनेक्टेड क्लाइंट और हर प्रॉक्सी के लिए ट्रैफिक काउंटर की सूची दिखाता है। यह "क्या होम बॉक्स अभी कनेक्टेड है" जैसे सवालों का जवाब पाने का सबसे तेज़ तरीका है। ssh सेशन बंद करते ही डैशबोर्ड फिर से अनरीचेबल हो जाता है।
टनल क्या नहीं करती है
इस भाग को दो बार पढ़ें, क्योंकि यहीं पर लोग गलती करते हैं। टनल एक private service को public internet से सुलभ बनाती है। यह उन लोगों को authenticate नहीं करती जो उस तक पहुँचते हैं। एक बार जब https://home.example.com resolve हो जाता है, तो scanners कुछ ही दिनों में इसे ढूंढ लेंगे, और वे इसे तब भी ढूंढ लेंगे चाहे आपने किसी को नाम बताया हो या नहीं। Certificate transparency logs हर उस hostname को प्रकाशित करते हैं जिसके लिए आप certificate जारी करते हैं, इसलिए certbot के सफल होते ही नाम public हो जाता है।
आप जो कुछ भी expose करते हैं, उसमें अपना authentication होना चाहिए। यदि app में rate limiting के साथ वास्तविक login है, तो यह अच्छा है। यदि इसका login एक साझा password है, या यदि इसमें कोई login नहीं है, तो VPS पर इसके सामने एक authenticating proxy लगाएँ। App के सामने लगा एक oauth2-proxy इसका सामान्य समाधान है, और यह टनल के दोनों सिरों में बिना किसी बदलाव के nginx और frp vhost के बीच फिट हो जाता है।
frps.toml में मौजूद token टनल की सुरक्षा करता है, apps की नहीं। यह किसी अजनबी को आपके VPS पर अपना proxy register करने से रोकता है। यह उस request के बारे में कुछ नहीं करता जो आपके द्वारा जानबूझकर publish किए गए hostname के लिए 443 port पर आती है।
दो आदतें बनाए रखना फायदेमंद है। दोनों files को edit करके और दोनों services को restart करके token को rotate करें, क्योंकि यह अपने आप कभी expire नहीं होता। और frp को current रखें: यह binary आपका public-facing front door है, और v0.71.0 के notes में client द्वारा भेजे गए गलत value से उत्पन्न server panic का उल्लेख है, जो कि उस तरह का bug है जिसे आप patch करना चाहेंगे, न कि जिसके बारे में तर्क करना।
विफलता के प्रकार और उनके संकेत
क्लाइंट कभी कनेक्ट नहीं होता है। journalctl -u frpc बार-बार connect to server error: दिखाता है, जिसके बाद dial timeout आता है। पोर्ट 7000 पर कुछ भी नहीं पहुँच रहा है। VPS पर ufw की जाँच करें, फिर कंट्रोल पैनल में प्रोवाइडर के नेटवर्क फायरवॉल को देखें, और अंत में पुष्टि करें कि नाम getent hosts vps.example.com के साथ रिजॉल्व हो रहा है।
टोकन गलत है। क्लाइंट इसे स्पष्ट शब्दों में बताता है:
login to the server failed: token in login doesn't match token from configurationटोकन को दोबारा कॉपी करें। एक trailing newline, या बिना कोट्स वाले शेल स्ट्रिंग में $ जो खाली हो गया हो, लगभग इन सभी समस्याओं का कारण बनता है। इसीलिए TOML फ़ाइल में openssl rand -base64 32 आउटपुट को कोट्स के अंदर रखना आवश्यक है।
टनल चालू है लेकिन ब्राउज़र केवल 404 दिखाता है। frpc ने सफल लॉगिन लॉग किया है और डैशबोर्ड प्रॉक्सी को सूचीबद्ध करता है, फिर भी पेज बिना किसी स्टाइलिंग के 404 त्रुटि देता है। इसका मतलब है कि frp रिपोर्ट कर रहा है कि उसके पास इस Host हेडर के लिए कोई प्रॉक्सी नहीं है। nginx और TLS दोनों को बायपास करते हुए, सीधे VPS पर vhost का परीक्षण करें:
# on the VPS
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: home.example.com' http://127.0.0.1:8080/उस कमांड से 404 मिलने का मतलब है कि customDomains गलत है। कोई अन्य कोड मिलने का मतलब है कि अनुरोध को nginx से सही Host नहीं मिला।
nginx से 502 त्रुटि। nginx जवाब दे रहा है और frp नहीं। VPS पर sudo ss -lntp | grep 8080 चलाने से दिखना चाहिए कि frps 127.0.0.1:8080 पर लिसन कर रहा है। खाली आउटपुट का मतलब है कि frps बंद है, या frps.toml में vhostHTTPPort सेट नहीं है।
ऐप को लगता है कि हर विज़िटर लोकल है। आपका ऐप हर अनुरोध के लिए 127.0.0.1 लॉग करता है। frp X-Forwarded-For सेट करता है और nginx उसमें जानकारी जोड़ता है, इसलिए वास्तविक क्लाइंट का पता उस हेडर में होता है। ऐप को इसे ट्रस्ट करने के लिए कॉन्फ़िगर करें। यदि ऐप IP एड्रेस के आधार पर रेट लिमिटिंग करता है, तो इसे अनदेखा न करें, क्योंकि अभी इंटरनेट का हर विज़िटर एक ही बकेट साझा कर रहा है।
लंबे अनुरोध 60 सेकंड पर कट जाते हैं। अपलोड या स्ट्रीमिंग रिस्पॉन्स बीच में ही रुक जाते हैं। यह टनल नहीं, बल्कि nginx का डिफ़ॉल्ट proxy_read_timeout है। ऊपर दिया गया ब्लॉक इसे 3600s तक बढ़ाता है। client_max_body_size अपलोड आकार के लिए संबंधित सीमा है, और इसका डिफ़ॉल्ट 1 MB मान बड़े बॉडी को 413 त्रुटि के साथ अस्वीकार कर देता है।
सब कुछ काम करता है, फिर राउटर रीबूट के बाद बंद हो जाता है। frpc यूनिट में Restart=always और साथ में loginFailExit = false इसे संभालते हैं। sudo systemctl is-enabled frpc के साथ पुष्टि करें, जिसे enabled प्रिंट करना चाहिए।
FAQ
मुझे कैसे पता चलेगा कि मैं CGNAT के पीछे हूँ?
अपने राउटर के एडमिन पेज पर मौजूद WAN एड्रेस की तुलना उस एड्रेस से करें जिसे curl -4 -s https://ifconfig.me उसी नेटवर्क के अंदर से रिपोर्ट करता है। यदि वे अलग हैं और राउटर का WAN एड्रेस 100.64.0.0/10 रेंज के भीतर है, तो आपका ISP carrier-grade NAT का उपयोग कर रहा है। वह रेंज RFC 6598 शेयर्ड एड्रेस स्पेस है और इसी उद्देश्य के लिए मौजूद है। कुछ ISP इसके बजाय WAN साइड पर 10.0.0.0/8 का उपयोग करते हैं, जिसका अर्थ भी वही है। यदि दोनों एड्रेस मेल खाते हैं, तो आपके पास एक पब्लिक IP है: पोर्ट फॉरवर्ड करें और आपका काम हो गया।
क्या मुझे रिवर्स टनल के लिए डोमेन नाम की आवश्यकता है?
यहाँ वर्णित HTTPS सेटअप के लिए, हाँ। एक सर्टिफिकेट किसी होस्टनेम के लिए जारी किया जाता है, और frp का HTTP vhost Host हेडर द्वारा अनुरोधों को रूट करता है, इसलिए दोनों सिरों पर एक नाम का होना जरूरी है जिस पर वे सहमत हों। एक नंबर्ड पोर्ट पर रॉ TCP प्रॉक्सी बिना किसी डोमेन के सीधे VPS के IP पर काम करता है, लेकिन तब आपके पास कोई सर्टिफिकेट और कोई होस्टनेम रूटिंग नहीं होती, इसलिए एक पब्लिक पोर्ट केवल एक ही सर्विस को सर्व कर पाता है।
क्या पब्लिक VPS पर frp चलाना सुरक्षित है?
यह तब सुरक्षित है जब केवल कंट्रोल पोर्ट ही एक्सपोज्ड हो और वह ऑथेंटिकेटेड हो। दोनों सिरों पर auth.token को एक रैंडम वैल्यू पर सेट करें और सर्वर पर transport.tls.force = true का उपयोग करें। फिर proxyBindAddr = "127.0.0.1" को सेट करें ताकि frp द्वारा प्रॉक्सी के लिए खोला गया कोई भी पोर्ट इंटरनेट के सामने न आए, और डैशबोर्ड को webServer.addr = "127.0.0.1" पर रखें, जिसे SSH लोकल फॉरवर्ड के माध्यम से एक्सेस किया जा सके। जब नए वर्ज़न रिलीज हों तो बाइनरी को अपडेट करें, क्योंकि यही वह प्रोसेस है जो आपके पब्लिक एड्रेस पर लिसन कर रही है।
मेरे ssh -R फॉरवर्डेड पोर्ट तक कोई क्यों नहीं पहुँच पा रहा है?
sshd डिफ़ॉल्ट रूप से GatewayPorts no के साथ आता है, इसलिए एक रिमोट फॉरवर्ड केवल VPS के लूपबैक इंटरफेस से ही बाइंड होता है। VPS पर ही चलाया गया curl काम करता है और कहीं और से किया गया curl टाइम-आउट हो जाता है। इसका सही समाधान यह है कि फॉरवर्ड को लूपबैक पर रहने दें और उसके सामने 443 पोर्ट पर nginx लगाएँ। GatewayPorts yes को सेट करने से बिना सर्टिफिकेट और बिना TLS के एक रॉ पोर्ट पब्लिश हो जाता है, जो उस समस्या से भी बदतर है जिसे यह हल करने का प्रयास करता है।
क्या मुझे frp का उपयोग करना चाहिए या Tailscale या WireGuard जैसे मेश VPN का?
जब केवल आपके अपने डिवाइस को एक्सेस की आवश्यकता हो, तो मेश VPN का उपयोग करें, क्योंकि तब कुछ भी पब्लिश नहीं होता और किसी के लिए स्कैन करने हेतु कोई पब्लिक होस्टनेम नहीं होता। जब आपको एक पब्लिक HTTPS एड्रेस की आवश्यकता हो जिसे कोई भी ब्राउज़र लोड कर सके, जैसे कि वेबहुक रिसीवर या कोई ऐसा पेज जिसे आप उन लोगों के साथ साझा करते हैं जो VPN क्लाइंट इंस्टॉल नहीं करेंगे, तब frp का उपयोग करें। ये दोनों एक ही VPS पर, अलग-अलग पोर्ट्स पर, अलग-अलग काम करते हुए आसानी से साथ रह सकते हैं।