This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
software:nginx:webdav [2015/05/12 23:56] – [Проблема 1 - Майкрософт нарушает стандарты и свои обещания] root | software:nginx:webdav [2022/02/05 04:30] (current) – root | ||
---|---|---|---|
Line 5: | Line 5: | ||
SAMB-у в принципе тоже без VPN можно пробросить, | SAMB-у в принципе тоже без VPN можно пробросить, | ||
- | Nginx в базовом функционале имеет не полную поддержку | + | Nginx в базовом функционале имеет не полную поддержку |
- | Расширить его ещё двумя: PROPFIND и OPTIONS можно с помощью | + | Расширить его ещё двумя: PROPFIND и OPTIONS можно с помощью |
- | Для работы потребуется Nginx собранный с поддержкой | + | Для работы потребуется Nginx собранный с поддержкой |
< | < | ||
[x] HTTP_DAV_EXT | [x] HTTP_DAV_EXT | ||
- | [x] HTTP_REWRITE | + | [x] HTTP_REWRITE |
+ | [x] HEADERS_MORE | ||
===== Проблема 1 - Майкрософт нарушает стандарты и свои обещания ===== | ===== Проблема 1 - Майкрософт нарушает стандарты и свои обещания ===== | ||
- | {{:ru: | + | {{: |
Перед тем как создать файл WebDav клиент проверяет наличие файла посылая запрос: | Перед тем как создать файл WebDav клиент проверяет наличие файла посылая запрос: | ||
Line 92: | Line 93: | ||
===== Проблема 2 - PROPPATCH отсутствует в nginx ===== | ===== Проблема 2 - PROPPATCH отсутствует в nginx ===== | ||
- | {{:ru: | + | {{: |
WebDav от мс очень хочет метод PROPPATCH, которого в Nginx и расширениях нет. Совсем нет.\\ | WebDav от мс очень хочет метод PROPPATCH, которого в Nginx и расширениях нет. Совсем нет.\\ | ||
Я рассматривал два варианта решения: | Я рассматривал два варианта решения: | ||
Line 98: | Line 99: | ||
2. Положится на кривость виндовой реализации WebDav и скормить статический ответ.\\ | 2. Положится на кривость виндовой реализации WebDav и скормить статический ответ.\\ | ||
- | Запрос: | + | Запрос: |
< | < | ||
Cache-Control: | Cache-Control: | ||
Line 109: | Line 110: | ||
Host: xxx.xxx.net | Host: xxx.xxx.net | ||
- | <?xml version=" | + | <?xml version=" |
- | <spoiler title=" | + | Ответ IIS: |
+ | <code> | ||
Date: Sun, 10 Aug 2014 12:24:47 GMT | Date: Sun, 10 Aug 2014 12:24:47 GMT | ||
Server: Microsoft-IIS/ | Server: Microsoft-IIS/ | ||
Line 123: | Line 125: | ||
И как эти все атрибуты писать в разных ОС и разных ФС?... | И как эти все атрибуты писать в разных ОС и разных ФС?... | ||
- | Так появился второй фикс в конфиге: | + | **Фикс 2** |
- | Фикс 2:\\ | + | |
< | < | ||
add_header Content-Type ' | add_header Content-Type ' | ||
Line 136: | Line 137: | ||
===== Проблема 3 - создание папок ===== | ===== Проблема 3 - создание папок ===== | ||
- | {{:ru: | + | {{: |
См п1 :) | См п1 :) | ||
- | Приходит запрос: | + | Приходит запрос: |
< | < | ||
Connection: Keep-Alive | Connection: Keep-Alive | ||
Line 147: | Line 148: | ||
Host: xxx.xxx.net</ | Host: xxx.xxx.net</ | ||
- | Nginx на него отвечает (немного странно выбирая код, на мой взгляд, | + | Nginx на него отвечает (немного странно выбирая код, на мой взгляд, |
- | Ответ:\\ | + | |
< | < | ||
Server: nginx/1.7.4 | Server: nginx/1.7.4 | ||
Line 168: | Line 168: | ||
Как должно быть описано: | Как должно быть описано: | ||
- | У майкрософта: | + | У майкрософта: |
- | У яндекса: | + | У яндекса: |
- | И даже в RFC: http:// | + | И даже в RFC: [[http:// |
Во всех примерах URL оканчивается слешем. \\ | Во всех примерах URL оканчивается слешем. \\ | ||
Line 176: | Line 176: | ||
Вариантов опять было два: \\ | Вариантов опять было два: \\ | ||
- | 1. Поправить файл: http:// | + | 1. Поправить файл: |
2. Пофиксить через конфиг.\\ | 2. Пофиксить через конфиг.\\ | ||
- | Вариант 1 я оставляю на усмотрение програмеров nginx, может по стандарту оно и должно ругаться. Связываться с отсылкой патчей тоже не хотелось.\\ | + | Вариант 1 я оставляю на усмотрение програмеров nginx, может по стандарту оно и должно ругаться.\\ |
- | **Фикс 3**:\\ | + | **Фикс 3**: |
< | < | ||
- | rewrite ^(.*[^/])$ $1/; | + | rewrite ^(.*[^/])$ $1/ break; |
}</ | }</ | ||
Вот для этого пустяка и потребовался REWRITE плагин.\\ | Вот для этого пустяка и потребовался REWRITE плагин.\\ | ||
Line 190: | Line 190: | ||
===== Проблема 4 - удаление папок ===== | ===== Проблема 4 - удаление папок ===== | ||
Ноги тут те же что и в п3: отсутствие слеша на конце урла.\\ | Ноги тут те же что и в п3: отсутствие слеша на конце урла.\\ | ||
- | Однако я столкнулся с тем, что nginx тоже ведёт себя несколько странно.\\ | + | Однако я столкнулся с тем, что nginx тоже ведёт себя несколько странно: если слеш на конце отсутствует, |
- | 1. Если слеш на конце отсутствует, | + | |
- | 2. Если слеш добавить то папку он почему то так и не удаляет. Подозреваю тут где то баг самого nginx.\\ | + | |
- | Фикс в конфиге: | ||
**Фикс 4**: | **Фикс 4**: | ||
< | < | ||
Line 206: | Line 204: | ||
open_file_cache off; | open_file_cache off; | ||
if (-d $webdav_root/ | if (-d $webdav_root/ | ||
- | rewrite ^(.*[^/])$ $1/; | + | rewrite ^(.*[^/])$ $1/ break; |
} | } | ||
root $webdav_root; | root $webdav_root; | ||
Line 212: | Line 210: | ||
}</ | }</ | ||
Если кратко, | Если кратко, | ||
+ | |||
+ | |||
+ | ===== Проблема 5 - копирование и переименование ===== | ||
+ | Ноги тут те же что и в п4: отсутствие слеша на конце урла и в Destination заголовке.\\ | ||
+ | Для решения проблемы с добавлением "/" | ||
+ | |||
+ | **Фикс 6**: | ||
+ | < | ||
+ | if ($request_method = COPY) { | ||
+ | return 597; | ||
+ | } | ||
+ | if ($request_method = MOVE) { | ||
+ | return 597; | ||
+ | } | ||
+ | |||
+ | location @copy_move_handler { | ||
+ | internal; | ||
+ | |||
+ | open_file_cache off; | ||
+ | if (-d $webdav_root/ | ||
+ | more_set_input_headers ' | ||
+ | rewrite ^(.*[^/])$ $1/ break; | ||
+ | } | ||
+ | root $webdav_root; | ||
+ | dav_methods COPY MOVE; | ||
+ | }</ | ||
+ | |||
+ | |||
+ | |||
+ | ===== Проблема 6 - OPTIONS корня ===== | ||
+ | Клиент запрашивает опции не у той папки которую мы хотим чтобы он подключил а у корня сервера.\\ | ||
+ | |||
+ | **Фикс 6**: | ||
+ | < | ||
+ | if ($request_method = OPTIONS) { | ||
+ | add_header Allow ' | ||
+ | add_header DAV '1, 2'; | ||
+ | return 200; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | Возвращаем ему статический список.\\ | ||
+ | Можно было просто разрешить: | ||
+ | |||
+ | |||
+ | ===== Проблема 7 - виндовый клиент не может подключится ===== | ||
+ | Соединение происходит но в логах nginx ничего нет, а клиент сообщает об ошибке.\\ | ||
+ | В логах с включённым дебагом ssl видно что рукопожатие не проходит.\\ | ||
+ | Проблема у меня проявилась не так давно, после обновления OpenSSL.\\ | ||
+ | При этом IE и другие браузеры могут авторизоваться по этому URL и отобразить листинг директории.\\ | ||
+ | |||
+ | **Фикс 7**: | ||
+ | Заменить OpenSSL на LibreSSL и пересобрать nginx. | ||
+ | Возможно OpenSSL уже исправили. | ||
Line 218: | Line 270: | ||
< | < | ||
и хотя в данном случае это не создаёт проблем, | и хотя в данном случае это не создаёт проблем, | ||
- | |||
- | Это уже третий раз когда гибкость nginx позволила мне получить результат не используя языки программирования, | ||
- | Прошлые разы я сделал кешируюший прокси с фильтрацией по урл и UPnP/DLNA сервер.\\ | ||
- | |||
Line 229: | Line 277: | ||
set $webdav_root "/ | set $webdav_root "/ | ||
location ^~ /Family { | location ^~ /Family { | ||
+ | if ($ssl_protocol = "" | ||
+ | add_header Strict-Transport-Security ' | ||
+ | return 403; | ||
+ | } | ||
+ | auth_basic " | ||
+ | auth_basic_user_file / | ||
- | root $webdav_root; | + | root $webdav_root; |
- | error_page 599 = @propfind_handler; | + | error_page 599 = @propfind_handler; |
- | error_page 598 = @delete_handler; | + | error_page 598 = @delete_handler; |
- | chunked_transfer_encoding on; | + | error_page 597 = @copy_move_handler; |
- | open_file_cache off; | + | open_file_cache off; |
- | client_max_body_size 50m; | + | client_max_body_size 50m; |
- | add_header Allow ' | + | |
if ($request_method = PROPFIND) { | if ($request_method = PROPFIND) { | ||
Line 246: | Line 299: | ||
} | } | ||
if ($request_method = MKCOL) { # Microsoft specific handle: add trailing slash. | if ($request_method = MKCOL) { # Microsoft specific handle: add trailing slash. | ||
- | rewrite ^(.*[^/])$ $1/; | + | rewrite ^(.*[^/])$ $1/ break; |
} | } | ||
if ($request_method = DELETE) { | if ($request_method = DELETE) { | ||
return 598; | return 598; | ||
+ | } | ||
+ | if ($request_method = COPY) { | ||
+ | return 597; | ||
+ | } | ||
+ | if ($request_method = MOVE) { | ||
+ | return 597; | ||
} | } | ||
- | dav_methods PUT MKCOL COPY MOVE; # | + | dav_methods PUT MKCOL; |
- | dav_ext_methods OPTIONS; | + | dav_ext_methods OPTIONS; |
create_full_put_path on; | create_full_put_path on; | ||
min_delete_depth 0; | min_delete_depth 0; | ||
- | dav_access user:rw group:rw all:rw; | + | dav_access user: |
+ | |||
+ | autoindex on; | ||
+ | autoindex_exact_size on; | ||
+ | autoindex_localtime on; | ||
} | } | ||
location @propfind_handler { | location @propfind_handler { | ||
internal; | internal; | ||
+ | |||
+ | auth_basic " | ||
+ | auth_basic_user_file / | ||
open_file_cache off; | open_file_cache off; | ||
Line 265: | Line 331: | ||
return 404; | return 404; | ||
} | } | ||
- | root $webdav_root; | + | root $webdav_root; |
- | dav_ext_methods PROPFIND; | + | dav_ext_methods PROPFIND; |
} | } | ||
location @delete_handler { | location @delete_handler { | ||
internal; | internal; | ||
+ | |||
+ | auth_basic " | ||
+ | auth_basic_user_file / | ||
open_file_cache off; | open_file_cache off; | ||
- | if (-d $webdav_root/ | + | if (-d $webdav_root/ |
- | rewrite ^(.*[^/])$ $1/; | + | rewrite ^(.*[^/])$ $1/ break; |
} | } | ||
- | root $webdav_root; | + | root $webdav_root; |
- | dav_methods DELETE; | + | dav_methods DELETE; |
- | }</ | + | } |
+ | location @copy_move_handler { | ||
+ | internal; | ||
+ | |||
+ | auth_basic " | ||
+ | auth_basic_user_file / | ||
+ | |||
+ | open_file_cache off; | ||
+ | if (-d $webdav_root/ | ||
+ | more_set_input_headers ' | ||
+ | rewrite ^(.*[^/])$ $1/ break; | ||
+ | } | ||
+ | root $webdav_root; | ||
+ | dav_methods COPY MOVE; | ||
+ | } | ||
+ | location / { | ||
+ | if ($request_method = OPTIONS) { | ||
+ | add_header Allow ' | ||
+ | add_header DAV '1, 2'; | ||
+ | return 200; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
open_file_cache off; | open_file_cache off; | ||
+ | Также в самом начале локейшена есть требование использовать SSL и если SSL используется то запрашивается BASIC авторизация. | ||
+ | ==== Важно ==== | ||
+ | - set $webdav_root "/ | ||
+ | - в папке "/ | ||
+ | - location ^~ **/Family** - означает что клиент должен использовать URL: https:// | ||
+ | - директивы **auth_basic** и **auth_basic_user_file** должны быть в каждом **location** который осуществляет обработку запросов, | ||
Line 286: | Line 383: | ||
Увы, но даже после всех проделанных настроек файлы более 4гб передавать не получится. (Скорее всего из за кривой реализации, | Увы, но даже после всех проделанных настроек файлы более 4гб передавать не получится. (Скорее всего из за кривой реализации, | ||
- | Вот здесь собраны все настройки с описанием: | + | Вот здесь собраны все настройки с описанием: |
На данный момент мои настройки WebClient выглядят так:\\ | На данный момент мои настройки WebClient выглядят так:\\ | ||
Line 306: | Line 403: | ||
+ | ===== Полезное ===== | ||
+ | * Дальнейшая разработка решения происходит тут: [[https:// | ||
+ | * Патч [[https:// | ||
+ | |||
+ | |||
+ | |||
+ | {{tag> |