Програма 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)

Тепер, коли я перевіряю, чи існує процес (як root, якщо щось приховано), прослуховування на порту 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

Слід зазначити, що у debian відкритий порт 80 як вхідне правило, якщо це має значення.

Моє запитання: Що я роблю не так? Як так, що я не можу визначити процес прослуховування порту 80? Чому це заблоковано в Debian? Які кроки мені слід зробити, щоб код працював правильно?

Відповіді:


197

Код помилки EACCESозначає, що у вас немає належних дозволів для запуску програм на цьому порту. У системах Linux будь-який порт нижче 1024 вимагає кореневого доступу.


5
таким чином, вузол sudo myapp.js зробить це, якщо у вас є дозвіл на використання sudo (просто прикріпити його для початківців).
AlexMA

20
@AlexMA, але запуск сервера як кореневого - це велике ні, ні
Патрік Еванс

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 у свіжій установці debian потрібно мати root, інакше $ PATH на це не вказуватиме.
Brian Yeh

Так, це був, мабуть, найпростіший спосіб зробити це. Я працюю в Google Cloud Compute, що викликало проблеми з торканням порту 80. Це було чудово. Дякую.
Енді,

Це має бути прийнятим рішенням. Запуск веб-сервера як sudo небезпечний, що потенційно може надати зловмиснику доступ до root, якщо в додатку є уразливість; також, якби програма мала створювати будь-які файли, вони були б недоступні для інших користувачів, змушуючи використовувати їх sudoще більше.
jesusiniesta

Не знаю, чому, але в Ubuntu 14.04 це не спрацювало для мене. Зараз я використовую переадресацію портів через ssh, що так само просто. Я розмістив відповідь нижче .
панепетер

19

Коротка відповідь: Ви можете дозволити доступ вузла до цього порту, використовуючи:

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запущено, ви можете створити зворотний проксі на 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.

Його потрібно запускати як root (привілейований порт). Щоб скасувати його, просто натисніть ctrl-c у терміналі. (Ви можете додати -fпрапор, щоб команда працювала у фоновому режимі, але тоді вам потрібно буде знайти його знову, щоб убити).

Це рішення вимагає, щоб сервер ssh працював локально . Це можна зробити швидко , але майте на увазі наслідки безпеки, якщо ви перебуваєте у спільній мережі. Можливо, ви захочете застосувати хоча б якийсь рівень додаткового захисту (вимкнути пароль і вхід у систему root).

Я особисто використовую це лише на своїй локальній машині. Я не впевнений, як це впливає на швидкість обробки ваших запитів, якщо ви запускаєте це на виробництві, можливо, хтось має ідею. У будь-якому випадку, вам потрібно було б переконатися, що ця команда постійно працює, що створює більше головного болю. Для виробничих середовищ я пропоную використовувати зворотний проксі-сервер, такий як nginx .


2

відповідь гексаціанідів є правильною. але чи є якесь рішення зробити цю роботу?

відповідь - так.

як?

Ви можете використовувати, reverse proxyнаприклад, запуск nginx reverse proxyon-port 80і передати проксі до місця призначення, ip:portяке використовує вузол.

Ви можете налаштувати це за допомогою, docker containerщо робить життя ще простішим. це офіційна збірка nginx у докер-концентраторі, яку ви можете витягнути.

Є ще більше переваг у використанні, reverse proxyщо ви можете погуглити його.


0

У мене така сама помилка, і я спробував запустити свою програму за допомогою 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)

і з судо

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

... що саме те, що ви не хочете робити. Це створює проблеми безпеки.
bvdb

-1

Використання PORT 80 вимагає деяких спеціальних дозволів. Використання sudoперед запуском оператора програми вирішило мою проблему. наприклад, якщо ви використовуєте npm для запуску своєї програми, ви можете ввестиsudo npm start


1
Ця відповідь нічого не додає до відповіді на вміст, вже наданий іншими. Будь ласка, дайте відповідь, лише якщо ви додаєте додаткову інформацію.
Brian Yeh

-2

Код помилки EACCESозначає, що у вас немає належних дозволів для запуску програм на цьому порту. У системах Linux будь-який порт нижче 1024 вимагає кореневого доступу.

Запустіть програму з sudoдозволом. Запустити sudo suкоманду перед запуском програми.


Див. Коментарі до публікації під відповіддю гексаціанідів. Дякую.
Brian Yeh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.