Site Tools


software:nginx:webdav

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next 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 в базовом функционале имеет не полную поддержку WebDav: PUT DELETE MKCOL COPY MOVE.\\ +Nginx в базовом функционале имеет не полную поддержку [[http://nginx.org/ru/docs/http/ngx_http_dav_module.html|Dav]]: PUT DELETE MKCOL COPY MOVE.\\ 
-Расширить его ещё двумя: PROPFIND и OPTIONS можно с помощью плагина: [[https://github.com/arut/nginx-dav-ext-module|dav-ext]]\\+Расширить его ещё двумя: PROPFIND и OPTIONS можно с помощью модуля: [[https://github.com/arut/nginx-dav-ext-module|dav-ext]]\\
  
  
-Для работы потребуется Nginx собранный с поддержкой WebDav, dav-ext модулем и rewrite.\\+Для работы потребуется Nginx собранный с поддержкой [[http://nginx.org/ru/docs/http/ngx_http_dav_module.html|Dav]][[https://github.com/arut/nginx-dav-ext-module|dav-ext]], [[http://nginx.org/ru/docs/http/ngx_http_rewrite_module.html|rewrite]] и [[http://wiki.nginx.org/HttpHeadersMoreModule|headers_more]].\\
 <code>[x] HTTP_DAV              Enable http_webdav module <code>[x] HTTP_DAV              Enable http_webdav module
 [x] HTTP_DAV_EXT          3rd party webdav_ext module [x] HTTP_DAV_EXT          3rd party webdav_ext module
-[x] HTTP_REWRITE          Enable http_rewrite module</code>+[x] HTTP_REWRITE          Enable http_rewrite module 
 +[x] HEADERS_MORE          3rd party headers_more module</code>
  
  
  
 ===== Проблема 1 - Майкрософт нарушает стандарты и свои обещания ===== ===== Проблема 1 - Майкрософт нарушает стандарты и свои обещания =====
-{{:ru:software:nginx:webdav1.png|}}+{{:software:nginx:webdav1.png|}}
  
 Перед тем как создать файл WebDav клиент проверяет наличие файла посылая запрос: Перед тем как создать файл WebDav клиент проверяет наличие файла посылая запрос:
Line 92: Line 93:
  
 ===== Проблема 2 - PROPPATCH отсутствует в nginx ===== ===== Проблема 2 - PROPPATCH отсутствует в nginx =====
-{{:ru:software:nginx:webdav2.png|}} \\+{{:software:nginx:webdav2.png|}} \\
 WebDav от мс очень хочет метод PROPPATCH, которого в Nginx и расширениях нет. Совсем нет.\\ WebDav от мс очень хочет метод PROPPATCH, которого в Nginx и расширениях нет. Совсем нет.\\
 Я рассматривал два варианта решения:\\ Я рассматривал два варианта решения:\\
Line 98: Line 99:
 2. Положится на кривость виндовой реализации WebDav и скормить статический ответ.\\ 2. Положится на кривость виндовой реализации WebDav и скормить статический ответ.\\
  
-Запрос:\\+Запрос:
 <code>PROPPATCH /Family/test.lnk HTTP/1.1 <code>PROPPATCH /Family/test.lnk HTTP/1.1
 Cache-Control: no-cache Cache-Control: no-cache
Line 109: Line 110:
 Host: xxx.xxx.net Host: xxx.xxx.net
  
-<?xml version="1.0" encoding="utf-8" ?><D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:"><D:set><D:prop><Z:Win32CreationTime>Sun, 10 Aug 2014 21:30:21 GMT</Z:Win32CreationTime><Z:Win32LastAccessTime>Sun, 10 Aug 2014 21:30:22 GMT</Z:Win32LastAccessTime><Z:Win32LastModifiedTime>Sun, 10 Aug 2014 21:30:22 GMT</Z:Win32LastModifiedTime><Z:Win32FileAttributes>00000020</Z:Win32FileAttributes></D:prop></D:set></D:propertyupdate></pre></spoiler>+<?xml version="1.0" encoding="utf-8" ?><D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:"><D:set><D:prop><Z:Win32CreationTime>Sun, 10 Aug 2014 21:30:21 GMT</Z:Win32CreationTime><Z:Win32LastAccessTime>Sun, 10 Aug 2014 21:30:22 GMT</Z:Win32LastAccessTime><Z:Win32LastModifiedTime>Sun, 10 Aug 2014 21:30:22 GMT</Z:Win32LastModifiedTime><Z:Win32FileAttributes>00000020</Z:Win32FileAttributes></D:prop></D:set></D:propertyupdate></code>
  
-<spoiler title="Ответ IIS"><pre>HTTP/1.1 207 Multi-Status+Ответ IIS
 +<code>HTTP/1.1 207 Multi-Status
 Date: Sun, 10 Aug 2014 12:24:47 GMT Date: Sun, 10 Aug 2014 12:24:47 GMT
 Server: Microsoft-IIS/6.0 Server: Microsoft-IIS/6.0
Line 123: Line 125:
 И как эти все атрибуты писать в разных ОС и разных ФС?... И как эти все атрибуты писать в разных ОС и разных ФС?...
  
-Так появился второй фикс в конфиге: +**Фикс 2**
-Фикс 2:\\+
 <code>if ($request_method = PROPPATCH) { # Unsupported, allways return OK. <code>if ($request_method = PROPPATCH) { # Unsupported, allways return OK.
  add_header Content-Type 'text/xml';  add_header Content-Type 'text/xml';
Line 136: Line 137:
  
 ===== Проблема 3 - создание папок ===== ===== Проблема 3 - создание папок =====
-{{:ru:software:nginx:webdav3.png|}} \\+{{:software:nginx:webdav3.png|}} \\
 См п1 :) См п1 :)
  
-Приходит запрос:\\+Приходит запрос:
 <code>MKCOL /Family/MR3020 HTTP/1.1 <code>MKCOL /Family/MR3020 HTTP/1.1
 Connection: Keep-Alive Connection: Keep-Alive
Line 147: Line 148:
 Host: xxx.xxx.net</code> Host: xxx.xxx.net</code>
  
-Nginx на него отвечает (немного странно выбирая код, на мой взгляд, но в принципе правильно)\\ +Nginx на него отвечает (немного странно выбирая код, на мой взгляд, но в принципе правильно):\\
-Ответ:\\+
 <code>HTTP/1.1 409 Conflict <code>HTTP/1.1 409 Conflict
 Server: nginx/1.7.4 Server: nginx/1.7.4
Line 168: Line 168:
  
 Как должно быть описано:\\ Как должно быть описано:\\
-У майкрософта: http://msdn.microsoft.com/en-us/library/aa142923(v=exchg.65).aspx \\ +У майкрософта: [[http://msdn.microsoft.com/en-us/library/aa142923(v=exchg.65).aspx]] \\ 
-У яндекса: http://api.yandex.ru/disk/doc/dg/reference/mkcol.xml \\ +У яндекса: [[http://api.yandex.ru/disk/doc/dg/reference/mkcol.xml]] \\ 
-И даже в RFC: http://tools.ietf.org/html/rfc2518#page-33 \\+И даже в RFC: [[http://tools.ietf.org/html/rfc2518#page-33]] \\
  
 Во всех примерах URL оканчивается слешем. \\ Во всех примерах URL оканчивается слешем. \\
Line 176: Line 176:
  
 Вариантов опять было два: \\ Вариантов опять было два: \\
-1. Поправить файл: http://lxr.nginx.org/source/src/http/modules/ngx_http_dav_module.c строчки 484 - 493, там как раз проверка наличия слеша и его отрезание. \\+1. Поправить файл: [[http://lxr.nginx.org/source/src/http/modules/ngx_http_dav_module.c]] строчки 484 - 493, там как раз проверка наличия слеша и его отрезание. \\
 2. Пофиксить через конфиг.\\ 2. Пофиксить через конфиг.\\
  
-Вариант 1 я оставляю на усмотрение програмеров nginx, может по стандарту оно и должно ругаться. Связываться с отсылкой патчей тоже не хотелось.\\+Вариант 1 я оставляю на усмотрение програмеров nginx, может по стандарту оно и должно ругаться.\\
  
-**Фикс 3**:\\+**Фикс 3**:
 <code>if ($request_method = MKCOL) { # Microsoft specific handle: add trailing slash. <code>if ($request_method = MKCOL) { # Microsoft specific handle: add trailing slash.
- rewrite ^(.*[^/])$ $1/;+ rewrite ^(.*[^/])$ $1/ break;
 }</code> }</code>
 Вот для этого пустяка и потребовался REWRITE плагин.\\ Вот для этого пустяка и потребовался REWRITE плагин.\\
Line 190: Line 190:
 ===== Проблема 4 - удаление папок ===== ===== Проблема 4 - удаление папок =====
 Ноги тут те же что и в п3: отсутствие слеша на конце урла.\\ Ноги тут те же что и в п3: отсутствие слеша на конце урла.\\
-Однако я столкнулся с тем, что nginx тоже ведёт себя несколько странно.\\ +Однако я столкнулся с тем, что nginx тоже ведёт себя несколько странно: если слеш на конце отсутствует, то nginx считает что его просят удалить файл, и получает ошибку: 21: Is a directory при попытке удалить.\\ 
-1. Если слеш на конце отсутствует, то nginx считает что его просят удалить файл, и получает ошибку: 21: Is a directory при попытке удалить.\\ +
-2. Если слеш добавить то папку он почему то так и не удаляет. Подозреваю тут где то баг самого nginx.\\+
  
-Фикс в конфиге:\\ 
 **Фикс 4**: **Фикс 4**:
 <code>error_page 598 = @delete_handler; <code>error_page 598 = @delete_handler;
Line 206: Line 204:
  open_file_cache off;  open_file_cache off;
  if (-d $webdav_root/$uri) { # Add trailing slash to dirs.  if (-d $webdav_root/$uri) { # Add trailing slash to dirs.
- rewrite ^(.*[^/])$ $1/;+ rewrite ^(.*[^/])$ $1/ break;
  }  }
  root $webdav_root;  root $webdav_root;
Line 212: Line 210:
 }</code> }</code>
 Если кратко, то переносим обработку DELETE в отдельный локейшин (процедуру), дальше проверяем, если удаляется папка то добавляем слеш.\\ Если кратко, то переносим обработку DELETE в отдельный локейшин (процедуру), дальше проверяем, если удаляется папка то добавляем слеш.\\
 +
 +
 +===== Проблема 5 - копирование и переименование =====
 +Ноги тут те же что и в п4: отсутствие слеша на конце урла и в Destination заголовке.\\
 +Для решения проблемы с добавлением "/" в заголовок Destinaton нам потребуется модуль headers_more.\\
 +
 +**Фикс 6**:
 +<code>error_page 597 = @copy_move_handler;
 +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/$uri) { # Add trailing slash to dirs.
 + more_set_input_headers 'Destination: $http_destination/';
 + rewrite ^(.*[^/])$ $1/ break;
 + }
 + root $webdav_root;
 + dav_methods COPY MOVE;
 +}</code>
 +
 +
 +
 +===== Проблема 6 - OPTIONS корня =====
 +Клиент запрашивает опции не у той папки которую мы хотим чтобы он подключил а у корня сервера.\\
 +
 +**Фикс 6**:
 +<code>location / {
 + if ($request_method = OPTIONS) {
 + add_header Allow 'OPTIONS, GET, HEAD, POST, PUT, MKCOL, MOVE, COPY, DELETE, PROPFIND, PROPPATCH';
 + add_header DAV '1, 2';
 + return 200;
 + }
 +}
 +</code>
 +Возвращаем ему статический список.\\
 +Можно было просто разрешить: dav_ext_methods OPTIONS;\\
 +
 +
 +===== Проблема 7 - виндовый клиент не может подключится =====
 +Соединение происходит но в логах nginx ничего нет, а клиент сообщает об ошибке.\\
 +В логах с включённым дебагом ssl видно что рукопожатие не проходит.\\
 +Проблема у меня проявилась не так давно, после обновления OpenSSL.\\
 +При этом IE и другие браузеры могут авторизоваться по этому URL и отобразить листинг директории.\\
 +
 +**Фикс 7**:
 +Заменить OpenSSL на LibreSSL и пересобрать nginx.
 +Возможно OpenSSL уже исправили.
  
  
Line 218: Line 270:
 <code>Content-Type: text/xml</code> <code>Content-Type: text/xml</code>
 и хотя в данном случае это не создаёт проблем, но всё же это не правильно.\\ и хотя в данном случае это не создаёт проблем, но всё же это не правильно.\\
- 
-Это уже третий раз когда гибкость nginx позволила мне получить результат не используя языки программирования, Игорь - молодец!\\ 
-Прошлые разы я сделал кешируюший прокси с фильтрацией по урл и UPnP/DLNA сервер.\\ 
- 
  
  
Line 229: Line 277:
 set $webdav_root "/mnt/WebDav_folder"; set $webdav_root "/mnt/WebDav_folder";
 location ^~ /Family { location ^~ /Family {
 + if ($ssl_protocol = "") { # Block non ssl/tls connections.
 + add_header Strict-Transport-Security 'max-age=600';
 + return 403;
 + }
 + auth_basic "Private site";
 + auth_basic_user_file /usr/local/etc/nginx/secure/authbasic.htpasswd;
  
- 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 'OPTIONS, GET, HEAD, DELETE, PUT, COPY, MOVE, PROPFIND';+
  
  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:rw group:rw all:rw
 + 
 + autoindex on; 
 + autoindex_exact_size on; 
 + autoindex_localtime on;
 } }
 location @propfind_handler { location @propfind_handler {
  internal;  internal;
 +
 + auth_basic "Private site";
 + auth_basic_user_file /usr/local/etc/nginx/secure/authbasic.htpasswd;
  
  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 "Private site";
 + auth_basic_user_file /usr/local/etc/nginx/secure/authbasic.htpasswd;
  
  open_file_cache off;  open_file_cache off;
- if (-d $webdav_root/$uri) { # Add trailing slash to dirs. + if (-d $webdav_root/$uri) { # Microsoft specific handle: Add trailing slash to dirs. 
- rewrite ^(.*[^/])$ $1/;+ rewrite ^(.*[^/])$ $1/ break;
  }  }
- root $webdav_root; + root $webdav_root; 
- dav_methods DELETE; + dav_methods DELETE; 
-}</code>+
 +location @copy_move_handler { 
 + internal; 
 + 
 + auth_basic "Private site"; 
 + auth_basic_user_file /usr/local/etc/nginx/secure/authbasic.htpasswd; 
 + 
 + open_file_cache off; 
 + if (-d $webdav_root/$uri) { # Microsoft specific handle: Add trailing slash to dirs. 
 + more_set_input_headers 'Destination: $http_destination/'; 
 + rewrite ^(.*[^/])$ $1/ break; 
 +
 + root $webdav_root; 
 + dav_methods COPY MOVE; 
 +
 +location / { 
 + if ($request_method = OPTIONS) { 
 + add_header Allow 'OPTIONS, GET, HEAD, POST, PUT, MKCOL, MOVE, COPY, DELETE, PROPFIND, PROPPATCH'; 
 + add_header DAV '1, 2'; 
 + return 200
 + } 
 +
 +</code>
  
 open_file_cache off; - нужно потому что мы меняем файлы, если кеширование включено то можно будет долго гадать почему не видно файлы которые мы только что закинули на сервер.\\ open_file_cache off; - нужно потому что мы меняем файлы, если кеширование включено то можно будет долго гадать почему не видно файлы которые мы только что закинули на сервер.\\
 +Также в самом начале локейшена есть требование использовать SSL и если SSL используется то запрашивается BASIC авторизация.
 +==== Важно ====
 +  - set $webdav_root "/mnt/WebDav_folder"; - **полный путь** на диске к папке которую мы расшариваем. Папка должна существовать и на неё должны быть выставлены права доступа которые позволят nginx получить доступ к содержимому, читать и записывать файлы.
 +  - в папке "/mnt/WebDav_folder" должна существовать папка Family
 +  - location ^~ **/Family** - означает что клиент должен использовать URL: https://SERVER_ADDRESS**/Family**
 +  - директивы **auth_basic** и **auth_basic_user_file** должны быть в каждом **location** который осуществляет обработку запросов, см [[https://github.com/dgraziotin/docker-nginx-webdav-nononsense/issues/15|DELETE requests work unauthenticated]]
  
  
Line 286: Line 383:
 Увы, но даже после всех проделанных настроек файлы более 4гб передавать не получится. (Скорее всего из за кривой реализации, которая файлы при открытии скачивает в память/на диск чтобы получить более менее стандартный файловый дискриптор, это мои домыслы.)\\ Увы, но даже после всех проделанных настроек файлы более 4гб передавать не получится. (Скорее всего из за кривой реализации, которая файлы при открытии скачивает в память/на диск чтобы получить более менее стандартный файловый дискриптор, это мои домыслы.)\\
  
-Вот здесь собраны все настройки с описанием: http://blogs.msdn.com/b/robert_mcmurray/archive/2008/01/17/webdav-redirector-registry-settings.aspx \\+Вот здесь собраны все настройки с описанием: [[http://blogs.msdn.com/b/robert_mcmurray/archive/2008/01/17/webdav-redirector-registry-settings.aspx]] \\
  
 На данный момент мои настройки WebClient выглядят так:\\ На данный момент мои настройки WebClient выглядят так:\\
Line 306: Line 403:
  
  
 +===== Полезное =====
 +  * Дальнейшая разработка решения происходит тут: [[https://github.com/dgraziotin/docker-nginx-webdav-nononsense|docker-nginx-webdav-nononsense]] - настоятельно рекомендую хотя бы посмотреть все решения которые там применены
 +  * Патч [[https://github.com/arut/nginx-dav-ext-module/pull/56|Fix PROPFIND fail with 500 on simlinks to non exist file/dir.]]
 +
 +
 +
 +{{tag>software howto windows net nginx WebDAV}}
software/nginx/webdav.1431474961.txt.gz · Last modified: 2015/05/12 23:56 by root