Eu preciso permitir que um usuário (diferente da raiz) execute um servidor que esteja escutando na porta 80.
Há alguma maneira de fazer isso?
Eu preciso permitir que um usuário (diferente da raiz) execute um servidor que esteja escutando na porta 80.
Há alguma maneira de fazer isso?
Respostas:
setcap 'cap_net_bind_service=+ep' /path/to/program
isso funcionará para processos específicos. Mas, para permitir que um usuário em particular se ligue a portas abaixo de 1024, será necessário adicioná-lo aos sudoers.
(Alguns desses métodos foram mencionados em outras respostas; estou dando várias opções possíveis em ordem aproximada de preferência.)
Você pode redirecionar a porta baixa para uma porta alta e ouvir na porta alta.
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 1080
Você pode iniciar o servidor como root e remover privilégios depois de começar a escutar na porta privilegiada. De preferência, em vez de codificar você mesmo, inicie o servidor a partir de um wrapper que faça o trabalho para você. Se o servidor iniciar uma instância por conexão, inicie-a em inetd
(ou em um programa semelhante como xinetd
). Para inetd
, use uma linha como esta em /etc/inetd.conf
:
http stream tcp nowait username:groupname /path/to/server/executable argv[0] argv[1]…
Se o servidor ouvir em uma única instância, inicie-o em um programa como authbind
. Crie um arquivo vazio /etc/authbind/byport/80
e torne-o executável para o usuário que está executando o servidor; ou create /etc/authbind/byuid/1234
, onde 1234 é o UID executando o servidor, contendo a linha 0.0.0.0/0:80,80
.
Se o seu executável do servidor é armazenado em um sistema de arquivos que suporta capacidades, você pode dar-lhe a capacidade . Cuidado que os recursos ainda são relativamente novos e ainda têm algumas distorções .cap_net_bind_service
setcap cap_net_bind_service=ep /path/to/server/executable
-A INPUT -p tcp --dport 1080 -j ACCEPT
caso contrário não funcionaria (também tenho um -j DROP
catch-all). Portanto, fico com dois soquetes de escuta.
A resposta curta é que isso não é possível por design.
A resposta longa é que, nos mundos de código aberto, há muitas pessoas brincando com o design e criando métodos alternativos. Em geral, é amplamente aceito que isso não deve ser possível. O fato de você estar tentando provavelmente significa que você tem outra falha de design em seu sistema e deve reconsiderar toda a arquitetura do sistema à luz das melhores práticas * nix e implicações de segurança.
Dito isto, um programa para autorizar o acesso não raiz a portas baixas é o authbind . Tanto o selinux quanto o grsecurity também fornecem estruturas para essas autenticações ajustadas.
Por fim, se você deseja que usuários específicos executem programas específicos como root e o que você realmente precisa é apenas para permitir que um usuário reinicie o apache ou algo parecido, sudo
é seu amigo!
Você pode usar o encaminhamento de porta netcat ou xinetd ou iptables ou usar o apache como proxy de front-end e executar o processo em uma porta não privilegiada.
Authbind , o @Gilles já mencionou, mas gostaria de expandir um pouco.
Possui controle de acesso conveniente (detalhes na página de manual): você pode filtrar o acesso por porta, endereço de interface, uid, intervalos de endereço ou porta e combinação destes.
Tem parâmetro muito útil --depth
:
--depth níveis
Faz com que o authbind afete programas com níveis profundos no gráfico de chamada. O padrão é 1.
"Níveis profundos" significa que quando um script (ou programa) executa outro script, ele desce um nível. Portanto, se você possui os --depth 5
níveis 1 (ou 0?) A 5, você tem permissão para vincular, enquanto no nível 6 e posterior, não. Útil quando você deseja que um script tenha acesso, mas não programas executados com ou sem o seu conhecimento.
Para ilustrar, você pode ter algo parecido com isto: por uma questão de segurança, você tem um usuário java
que deve executar apenas java e deseja dar a ele acesso à porta 80:
echo > /etc/authbind/byport/80
chown root:java /etc/authbind/byport/80
chmod 710 /etc/authbind/byport/80
Eu criei o ../byport/80 file
, entreguei ao java
grupo de usuários (cada usuário tem seu próprio grupo) e o tornei executável por grupo, o que significa que é executável por java
usuário. Se você está dando acesso por porta, o arquivo deve ser executável pelo usuário que deve ter acesso, então fizemos isso.
Isso pode ser suficiente para o Joe médio, mas como você sabe usar o --depth
parâmetro, você executa (como java
usuário) authbind --depth [depth] my_web_app's_start_script
iniciando --depth 1
e trabalhando até encontrar a menor profundidade que funcione e a use.
Tentei o método iptables PREROUTING REDIRECT, mas descobri que ele também afeta pacotes encaminhados. Ou seja, se a máquina também estiver encaminhando pacotes entre interfaces (por exemplo, se estiver atuando como um ponto de acesso Wi-Fi conectado a uma rede Ethernet), a regra iptables também capturará as conexões dos clientes conectados aos destinos da Internet e as redirecionará para a máquina. Não era isso que eu queria; eu só queria redirecionar as conexões direcionadas à própria máquina.
Uma possibilidade é usar o encaminhamento de porta TCP. Por exemplo, usando socat
:
socat TCP4-LISTEN:www,reuseaddr,fork TCP4:localhost:8080
No entanto, uma desvantagem desse método é que o aplicativo que está escutando na porta 8080 não conhece o endereço de origem das conexões de entrada (por exemplo, para log ou outros fins de identificação).