Настройте Spring Boot + tomcat 8 для работы на непривилегированном порту

У меня есть работающее встроенное приложение spring boot + tomcat8, которое привязывается к портам 8080 (http) и 8888 (https). Теперь я ищу способ настроить приложение для запуска

а) на привилегированном порту, т.е. на порте ниже 1024, т.е. на портах 80 и 443

б) приложение должно работать под учетной записью пользователя без полномочий root.

c) среда ОС может быть любым дистрибутивом Linux, например: дистрибутив debian/ubuntu или OpenBSD.

г) желательно, чтобы решение впоследствии настраивалось через веб-интерфейс, т. е. через какой-нибудь скрипт.

Все, что я пока нашел в ИНТЕРНЕТЕ, — это руководство по настройке не встроенного экземпляра tomcat вместе с «authbind». Однако у меня есть встроенный кот. Страница руководства «authbind» говорит:

«Вы должны вызвать программу, используя authbind. authbind установит некоторые переменные среды, в том числе LD_PRELOAD, что позволит программе (включая любые подпроцессы, которые она может запускать) связываться с портами с низким номером (‹512), если система настроена на это. “

Я выдал «ps — aux» и получил имя пользователя, под которым запущено приложение. Я настроил встроенный tomcat для работы на портах 80 и 443 портов, т.е. и выдал команды в cli:

sudo touch /etc/authbind/byport/80
sudo chmod 500 /etc/authbind/byport/80
chown tito /etc/authbind/byport/80
sudo touch /etc/authbind/byport/443
sudo chmod 500 /etc/authbind/byport/443
chown tito /etc/authbind/byport/443

Теперь, как мне вызвать встроенный кот под «authbind». Если «authbind» не является правильным решением этой проблемы, то как решить эту проблему с помощью весенней загрузки.

Сообщение об ошибке, которое я получаю:

2014-05-09 09:46:48.403  INFO 7880 --- [           main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 80
2014-05-09 09:46:48.604 ERROR 7880 --- [           main] o.a.coyote.http11.Http11NioProtocol      : Failed to initialize end point associated with ProtocolHandler ["http-nio-80"]

java.net.SocketException: Permission denied
    at sun.nio.ch.Net.bind0(Native Method)
    at sun.nio.ch.Net.bind(Net.java:414)
    at sun.nio.ch.Net.bind(Net.java:406)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:214)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
    at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:351)
    at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:683)
    at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:456)
    at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:120)
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:960)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardService.initInternal(StandardService.java:567)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:826)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:340)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:79)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:69)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:270)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:145)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:159)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:132)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:476)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
    at org.syncServer.core.Application.main(Application.java:123)

2014-05-09 09:46:48.606 ERROR 7880 --- [           main] o.apache.catalina.core.StandardService   : Failed to initialize connector [Connector[HTTP/1.1-80]]

org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-80]]
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
    at org.apache.catalina.core.StandardService.initInternal(StandardService.java:567)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:826)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:139)
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:340)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:79)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:69)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:270)
    at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:145)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:159)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:132)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:476)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
    at org.syncServer.core.Application.main(Application.java:123)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:962)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    ... 19 common frames omitted
Caused by: java.net.SocketException: Permission denied
    at sun.nio.ch.Net.bind0(Native Method)
    at sun.nio.ch.Net.bind(Net.java:414)
    at sun.nio.ch.Net.bind(Net.java:406)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:214)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
    at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:351)
    at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:683)
    at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:456)
    at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:120)
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:960)
    ... 20 common frames omitted

2014-05-09 09:46:48.840  INFO 7880 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2014-05-09 09:46:48.841  INFO 7880 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.3
2014-05-09 09:46:48.913  INFO 7880 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-05-09 09:46:48.913  INFO 7880 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1898 ms
SERVLET REGISTRATION
DISPATCHER INIT

ДОПОЛНЕНИЕ 1 я нашел способ сделать это из командной строки, т.е. с весны я делаю сборку maven с целью «пакет», затем я иду в целевую папку, где находится мой файл jar/war, а затем я делаю

exec authbind --deep java -jar application.jar 

Приложение привязано к портам 80 и 443, но мои шаблоны mvc thymeleaf каким-то образом испортились. Мне нужно автоматизировать этот процесс через spring sts


person Tito    schedule 09.05.2014    source источник


Ответы (2)


Читая между строк, вы пытаетесь открыть свое приложение Spring Boot на порту 80/443, но вам действительно не нужно, чтобы оно прослушивало один из этих портов. Вместо этого вам следует использовать обратный прокси-сервер, такой как HAProxy, который запускается как root, но затем блокирует себя в chroot, чтобы у него не было привилегий root.

Затем вы настраиваете прокси для пересылки запросов на любой порт, который слушает ваше приложение.

Помимо безопасности, у этого есть дополнительные преимущества, такие как возможность переадресации на основе URL-адреса, используемого для нескольких служб. Это замечательно для микросервисов Spring Boot, поскольку позволяет открывать несколько сервисов через порты 80/443 на одном сервере, не предоставляя ни одному из этих приложений привилегий root. Его также можно использовать для обеспечения «горячего» переключения между экземплярами приложений, что может помочь вам добиться развертывания с нулевым временем простоя.

Популярными альтернативами HAProxy являются Apache HTTPD и Nginx.

person Steve    schedule 09.05.2014
comment
привет Стив, спасибо за ответ. эта идея интересна, и я определенно рассмотрю HAProxy для будущих проектов, однако в этом проекте у меня есть учетная запись root, и я бы установил прокси, но я не знаю, что использовать какой-либо дополнительный уровень, т. е. haProxy и т. д. Так есть ли какой-либо другой способ связать приложение весенней загрузки со встроенным tomcat непосредственно на портах 80 и 443. - person Tito; 09.05.2014
comment
Не без запуска его как root - по крайней мере, насколько мне известно - person Steve; 09.05.2014
comment
хорошо, я нашел способ сделать это из командной строки, т.е. с весны я делаю сборку maven с целевым пакетом, затем я иду в целевую папку, где находится мой файл jar/war, а затем я делаю exec authbind --deep java -jar application.jar Приложение привязано к портам 80 и 443, но мои шаблоны mvc почему-то не работают. Мне нужно автоматизировать этот процесс через spring sts - person Tito; 09.05.2014
comment
Вы можете просто использовать iptables для переадресации 80 и 443 на порты, которые прослушивает Tomcat. Я делаю то же самое на своем Mac для разработки. - person chad; 13.09.2014
comment
это не совсем то, что я искал, то есть делать переадресацию портов - person Tito; 23.10.2014

Весь необходимый вам персонал реализован в инструментах Apache Daemon.

Он предоставляет chroot для Java-приложений. Таким образом, вы можете запустить его как root и привязать к привилегированному порту, а затем понизить его до непривилегированного пользователя.

person ursa    schedule 05.10.2014