แอป Node.js ไม่สามารถทำงานบนพอร์ต 80 แม้ว่าจะไม่มีกระบวนการอื่นใดที่บล็อกพอร์ต


94

ฉันใช้งานอินสแตนซ์ของ Debian บน Amazon EC2 ที่ติดตั้ง Node.js หากฉันเรียกใช้รหัสด้านล่าง:

http = require('http');

http.createServer(function (request, response){
  response.writeHead(200, {'Content-Type':'text/plain'});
  response.end('Hello World\n');
}).listen(80);
console.log("Running server at port 80");

ฉันได้รับผลลัพธ์ด้านล่างซึ่งบอกฉันว่ามีกระบวนการอื่นฟังที่พอร์ต 80:

Running server at port 80

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: listen EACCES
    at errnoException (net.js:901:11)
    at Server._listen2 (net.js:1020:19)
    at listen (net.js:1061:10)
    at Server.listen (net.js:1127:5)
    at Object.<anonymous> (/home/admin/nodetests/nodetest.js:6:4)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

ตอนนี้เมื่อฉันตรวจสอบดูว่ามีกระบวนการหรือไม่ (เนื่องจากรูทในกรณีที่มีสิ่งใดซ่อนอยู่) ฟังบนพอร์ต 80 โดยใช้:

netstat -tupln

ฉันได้รับเอาต์พุตด้านล่างซึ่งบอกว่าไม่มีอะไรฟังที่พอร์ต 80:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1667/sshd       
tcp6       0      0 :::22                   :::*                    LISTEN      1667/sshd

ฉันควรทราบว่าเดเบียนมีพอร์ต 80 เปิดเป็นกฎขาเข้าหากสิ่งนั้นสร้างความแตกต่าง

คำถามของฉันคือฉันทำอะไรผิด? ทำไมฉันไม่สามารถระบุกระบวนการฟังพอร์ต 80 ได้? เหตุใดจึงถูกบล็อกใน Debian ฉันควรทำขั้นตอนใดเพื่อให้โค้ดทำงานอย่างถูกต้อง

คำตอบ:


198

รหัสข้อผิดพลาดEACCESหมายความว่าคุณไม่มีสิทธิ์ที่เหมาะสมในการเรียกใช้แอปพลิเคชันบนพอร์ตนั้น บนระบบ Linux พอร์ตใด ๆ ที่ต่ำกว่า 1024 ต้องการการเข้าถึงรูท


5
ดังนั้น sudo node myapp.js จะทำหากคุณได้รับอนุญาตให้ใช้ sudo (เพียงแค่เปิดใช้งานสำหรับผู้เริ่มต้น)
AlexMA

21
@AlexMA แต่การใช้งานเซิร์ฟเวอร์ในฐานะรูทเป็นเรื่องใหญ่ไม่
Patrick Evans

1
แล้วคุณจะรันโหนดบนพอร์ต 80 ได้อย่างไร? คุณควร ... ไม่ใช่และใช้พร็อกซี?
AlexMA

9
@PatrickEvans ฉันคิดว่าแนวทางปฏิบัติที่ดีที่สุดคือการรันบนพอร์ตอื่นและตั้งค่ากฎการส่งต่อพอร์ตตามที่กล่าวไว้ที่นี่: stackoverflow.com/questions/16573668/…
AlexMA

73

แทนที่จะทำงานบนพอร์ต 80 คุณสามารถเปลี่ยนเส้นทางพอร์ต 80 ไปยังพอร์ตของแอปพลิเคชันของคุณ (> 1024) โดยใช้ไฟล์

iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000

สิ่งนี้จะใช้ได้ถ้าแอปพลิเคชันของคุณทำงานบนพอร์ต 3000


1
ทำสิ่งนี้ พบว่าคุณต้องรูทเพื่อรัน iptables ในการติดตั้งเดเบียนใหม่มิฉะนั้น $ PATH จะไม่ชี้ไปที่มัน
Brian Yeh

ใช่นี่อาจเป็นวิธีที่ง่ายที่สุดที่จะทำ ฉันใช้ Google Cloud Compute ซึ่งทำให้ฉันมีปัญหาเมื่อแตะพอร์ต 80 นี่เยี่ยมมาก ขอบคุณ.
Andy

นี่ควรเป็นทางออกที่ได้รับการยอมรับ การเรียกใช้เว็บเซิร์ฟเวอร์เนื่องจาก sudo เป็นอันตรายและอาจทำให้ผู้โจมตีเข้าถึงรูทได้หากมีช่องโหว่ในแอปพลิเคชัน นอกจากนี้หากแอปพลิเคชันสร้างไฟล์ใด ๆ ผู้ใช้รายอื่นจะไม่สามารถเข้าถึงได้ทำให้คุณใช้งานsudoได้มากขึ้น
jesusiniesta

ไม่แน่ใจว่าทำไม แต่บน Ubuntu 14.04 สิ่งนี้ใช้ไม่ได้สำหรับฉัน ตอนนี้ฉันใช้การส่งต่อพอร์ตผ่าน ssh ซึ่งง่ายพอ ๆ ผมโพสต์คำตอบด้านล่าง
panepeter

20

คำตอบสั้น ๆ : คุณสามารถอนุญาตให้โหนดเข้าถึงพอร์ตนั้นโดยใช้:

setcap 'cap_net_bind_service=+ep' /path/to/nodejs

คำตอบยาว

แก้ไข:

อาจไม่ทำงานกับโหนดเวอร์ชันใหม่


นั่นเป็นเคล็ดลับ @LinuxMint - sudo setcap 'cap_net_bind_service = + ep' / usr / local / bin / node
รวม

บางครั้งการอัปเดตจะเปลี่ยนเส้นทางตำแหน่งไปยังโหนดและสิ่งนี้จะหยุดทำงาน ดังนั้นคุณจะต้องเรียกใช้อีกครั้งสำหรับเส้นทางใหม่ไปยังโหนด
นึ่ง

ดูเหมือนว่าสิ่งนี้จะใช้ไม่ได้อีกต่อไปในโหนดเวอร์ชัน 8. github.com/nodejs/node/issues/22648
timaw

6

โปรดทราบว่าหากคุณapacheรันอยู่คุณสามารถสร้าง reverse proxy บน vhost ได้ หากโหนดของคุณกำลังทำงานบนพอร์ต8080:

<VirtualHost 127.0.0.1:80>
        ServerName myLocalServer

        ProxyPass        /  http://localhost:8080/
        ProxyPassReverse /  http://localhost:8080/
</VirtualHost>

แน่นอนเพิ่มเซิร์ฟเวอร์ไปที่/etc/hosts:

127.0.0.1    myLocalServer

คุณจะต้องเปิดใช้งานโมดูล apache ที่เกี่ยวข้อง:

sudo a2enmod proxy_html
sudo a2enmod proxy_http
sudo a2enmod proxy_connect
sudo a2enmod proxy_ajp
sudo service apache2 restart

... http://myLocalServerและตอนนี้คุณสามารถเชื่อมต่อกับ


3

สำหรับผู้ที่กำลังมองหาโซลูชันที่ง่ายและรวดเร็วสำหรับสภาพแวดล้อมการพัฒนาการส่งต่อพอร์ตผ่าน ssh อาจเป็นทางเลือกที่ดี:

ssh -L 80:localhost:3000 yourusername@localhost -N

ส่งต่อพอร์ต 80 บน localhost ไปยังพอร์ต 3000 บน localhost

จำเป็นต้องรันในฐานะรูท (พอร์ตที่มีสิทธิพิเศษ) หากต้องการยกเลิกเพียงกด ctrl-c ในเทอร์มินัล (คุณสามารถเพิ่ม-fแฟล็กเพื่อให้คำสั่งทำงานอยู่เบื้องหลัง แต่คุณต้องหาอีกครั้งเพื่อฆ่ามัน)

โซลูชันนี้ต้องการให้คุณมีเซิร์ฟเวอร์ ssh ที่ทำงานในเครื่อง สามารถทำได้อย่างรวดเร็วแต่โปรดคำนึงถึงผลกระทบด้านความปลอดภัยหากคุณอยู่ในเครือข่ายที่ใช้ร่วมกัน คุณอาจต้องการใช้การรักษาความปลอดภัยเพิ่มเติมอย่างน้อยระดับหนึ่ง (ปิดใช้งานรหัสผ่านและการเข้าสู่ระบบรูท)

โดยส่วนตัวฉันเคยใช้สิ่งนี้กับเครื่องในพื้นที่ของฉันเท่านั้น ฉันไม่แน่ใจว่าจะส่งผลต่อความเร็วในการประมวลผลคำขอของคุณอย่างไรหากคุณเรียกใช้สิ่งนี้ในการผลิตอาจมีคนคิด อย่างไรก็ตามคุณจะต้องตรวจสอบให้แน่ใจว่าคำสั่งนี้ทำงานตลอดเวลาซึ่งจะทำให้ปวดหัวมากขึ้น สำหรับสภาพแวดล้อมการผลิตผมขอแนะนำให้ใช้พร็อกซี่กลับเหมือน Nginx


2

คำตอบของ hexacyanide นั้นถูกต้อง แต่จะมีวิธีใดที่จะทำให้งานนี้ได้?

คำตอบคือใช่

ยังไง

คุณสามารถใช้reverse proxyตัวอย่างเช่นรันnginx reverse proxyพอร์ตบน80และส่งพร็อกซีไปยังปลายทางip:portที่โหนดใช้

คุณสามารถตั้งค่าโดยใช้docker containerที่ทำให้ชีวิตง่ายยิ่งขึ้น นี่คือโครงสร้างอย่างเป็นทางการของ nginxใน docker hub ที่คุณสามารถดึงได้

มีประโยชน์มากยิ่งขึ้นในการใช้งานreverse proxyที่คุณสามารถใช้ Google ได้


0

ฉันได้รับข้อผิดพลาดเดียวกันและฉันพยายามเรียกใช้แอปพลิเคชันของฉันโดยใช้ sudo และมันก็ใช้ได้ผลสำหรับฉัน

ไม่มี sudo

mansi@mansi:~/NodePractice$ node myFirst.js 
events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: listen EACCES 0.0.0.0:80
    at Object.exports._errnoException (util.js:870:11)
    at exports._exceptionWithHostPort (util.js:893:20)
    at Server._listen2 (net.js:1224:19)
    at listen (net.js:1273:10)
    at Server.listen (net.js:1369:5)
    at Object.<anonymous> (/home/mansi/NodePractice/myFirst.js:6:4)
    at Module._compile (module.js:410:26)
    at Object.Module._extensions..js (module.js:417:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)

และด้วย sudo

mansi@mansi:~/NodePractice$ sudo node myFirst.js 
^C

... ซึ่งเป็นสิ่งที่คุณไม่ต้องการทำ มันสร้างปัญหาด้านความปลอดภัย
bvdb

-2

รหัสข้อผิดพลาดEACCESหมายความว่าคุณไม่มีสิทธิ์ที่เหมาะสมในการเรียกใช้แอปพลิเคชันบนพอร์ตนั้น บนระบบ Linux พอร์ตใด ๆ ที่ต่ำกว่า 1024 ต้องการการเข้าถึงรูท

รันโปรแกรมด้วยการsudoอนุญาต รันsudo suคำสั่งก่อนรันโปรแกรม


ดูความคิดเห็นของโพสต์ใต้คำตอบ hexacyanides ขอบคุณ.
Brian Yeh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.