Назад | Перейти на главную страницу

Сценарию CGI не удается открыть сокет (CentOS 6.2 / Apache2)

У меня есть веб-сервер под управлением CentOS 6.2 и последней версии Apache из репозиториев. Todey Я столкнулся с проблемой при запуске исполняемой программы через CGI на Apache. Программа должна подключиться к какому-либо сайту, загрузить что-то и затем вернуть это пользователю (обычный запрос порта 80, ничего подозрительного).

Проблема в том, что программы CGI возвращают Permission denied на socket_open команда.

Другие более простые программы CGI, которые не требуют подключения к сети, работают нормально, и эта программа работает так же хорошо, когда вызывается из командной строки, поэтому я подозревал, что есть проблемы с разрешениями, и поскольку setuid на исполняемом файле не решила проблему, я пришел к выводу, что это то, что контролирует SELinux.

Я никогда особо не работал с SELinux, но getsebool -a | grep httpd возвращается

allow_httpd_anon_write --> off
allow_httpd_mod_auth_ntlm_winbind --> off
allow_httpd_mod_auth_pam --> off
allow_httpd_sys_script_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_network_connect --> off
httpd_can_network_connect_cobbler --> off
httpd_can_network_connect_db --> off
httpd_can_network_memcache --> off
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_dbus_avahi --> on
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> off
httpd_execmem --> off
httpd_read_user_content --> off
httpd_setrlimit --> off
httpd_ssi_exec --> off
httpd_tmp_exec --> off
httpd_tty_comm --> on
httpd_unified --> on
httpd_use_cifs --> off
httpd_use_gpg --> off
httpd_use_nfs --> off

Я подозреваю что httpd_can_network_connect --> off здесь проблематичный, но это разрешение для httpd, а не сам исполняемый файл. Унаследованы ли разрешения SELinux от родительского процесса? Как бы включить его только для сценария, а не для всего? httpd? Или это совсем другая проблема, не связанная с SELinux?

Спасибо за помощь.

Редактировать: Я попытался setenforce 0 и скрипт тогда работает, так что это вещь SELinux.

Редактировать 2: ausearch -ts recent -m avc возвращается

time->Thu May  3 23:52:29 2012
type=SYSCALL msg=audit(1336081949.221:18563): arch=c000003e syscall=42 success=no exit=-13 a0=8 a1=7fff21161cb0 a2=10 a3=7fff21161a30 items=0 ppid=6813 pid=6814 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm=".stutsk" exe="/var/www/html/stutsk-cgi/.stutsk" subj=system_u:system_r:httpd_sys_script_t:s0 key=(null)
type=AVC msg=audit(1336081949.221:18563): avc:  denied  { name_connect } for  pid=6814 comm=".stutsk" dest=80 scontext=system_u:system_r:httpd_sys_script_t:s0 tcontext=system_u:object_r:http_port_t:s0 tclass=tcp_socket

Унаследованы ли разрешения SELinux от родительского процесса?

Да, если правило не вызывает переход на новый домен.

Как сделать так, чтобы он был включен только для сценария, а не для всего httpd?

Вам потребуется создать новый домен, разрешающий доступ к сети, и написать правило, которое вызывает переход домена при вызове интерпретатора сценария. Обратите внимание, что это приведет к тому, что любой сценарий, вызываемый этим интерпретатором при вызове httpd, будет следовать этому переходу; гораздо менее тривиально вызвать переход домена для конкретного сценария.

Лично у меня были бы оговорки, чтобы разрешить обработке CGI получать данные из сети (просто заставляет меня чувствовать себя некомфортно), но вы можете включить это с помощью следующей политики:

policy_module(localhttpd_script_t, 1.0.0)

gen_require(`
        type httpd_sys_script_t;
        type http_port_t;
')

gen_tunable(`httpd_script_can_http_connect', `false')

tunable_policy(`httpd_script_can_http_connect', `
        allow httpd_sys_script_t self:tcp_socket rw_socket_perms;
        corenet_tcp_connect_http_port(httpd_sys_script_t)
        corenet_tcp_sendrecv_http_port(httpd_sys_script_t)
')

Вам нужно будет установить policycoreutils-python вещи, если это еще не сделано.

Для этого запустите

make -f /usr/share/selinux/devel/Makefile load

Это скомпилирует и установит модуль. Я скомпилировал Fedora 15, но не думаю, что для этой системы есть какие-то особые правила.

Чтобы включить это (временно), выполните команду setsebool httpd_script_can_http_connect 1 и сделать постоянным setsebool -P httpd_script_can_http_connect 1 .