Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

아파치 서버 2.4를 위한 mod_aspdotnet 마이그레이션

지난 글에서 소개한,

아파치 서버에서 ASP.NET을 실행하는 mod_aspdotnet 모듈
; https://www.sysnet.pe.kr/2/0/11290

mod_aspdotnet 모듈이 현재 개발자의 사정인지 2009년 이래로 더 이상 업데이트가 안되고 있습니다. 그래서, 별로 기능 업데이트를 할 수는 없지만 Apache 2.4에서도 돌아갈 수 있게끔 변경한 버전을 다음의 github에 배포했습니다.

stjeong/mod_aspdotnet
; https://github.com/stjeong/mod_aspdotnet

개인적으로도 사실 시간이 많지 않아 별로 기능 업데이트를 할 생각은 없지만 그래도 누군가 contributor로 참여해 기능을 추가할 수 있는 여지는 남기는 것이 좋을 것 같아 repo를 열었습니다. (관심있으신 분은 참여를! ^^)




우선, 소스코드는 다음의 마지막 snapshot을 이용했습니다.

mod-aspdotnet-code-222.zip
; https://sourceforge.net/p/mod-aspdotnet/code/HEAD/tarball

Apache 2.4 지원을 위해 xampp를 이용해 설치한 아파치 서버의 include, lib 폴더를 사용했습니다.

나머지 작업은 이제 Apache 2.4로 소스코드를 마이그레이션하는 건데요. 다음의 문서에 따라 은근히 변한 것이 있습니다.

API Changes in Apache HTTP Server 2.4 since 2.2
; https://httpd.apache.org/docs/2.4/developer/new_api_2_4.html

우선, remote_ip와 remote_addr 필드가 변경되었습니다.

conn_rec->remote_ip and conn_rec->remote_addr
  ==> conn_rec->client_ip and conn_rec->client_addr

또한, ap_log_... 관련 함수에 3번째 인자로 module_index가 추가되었습니다.

#ifdef DOXYGEN
AP_DECLARE(void) ap_log_rerror(const char *file, int line, int module_index,
                               int level, apr_status_t status,
                               const request_rec *r, const char *fmt, ...);
#else
#ifdef AP_HAVE_C99
/* need additional step to expand APLOG_MARK first */
#define ap_log_rerror(...) ap_log_rerror__(__VA_ARGS__)
#define ap_log_rerror__(file, line, mi, level, status, r, ...)              \
    do { if (APLOG_R_MODULE_IS_LEVEL(r, mi, level))                         \
             ap_log_rerror_(file, line, mi, level, status, r, __VA_ARGS__); \
    } while(0)
#else
#define ap_log_rerror ap_log_rerror_
#endif
AP_DECLARE(void) ap_log_rerror_(const char *file, int line, int module_index,
                                int level, apr_status_t status,
                                const request_rec *r, const char *fmt, ...)
                                __attribute__((format(printf,7,8)));
#endif

아파치 모듈 인덱스는 소스 코드에 AP_DECLARE_MODULE를 해주면 된다고 해서 포함시켰습니다.

#ifdef AP_DECLARE_MODULE
AP_DECLARE_MODULE(mod_aspdotnet);
#endif

그 외에 다음과 같은 컴파일 오류가 발생했는데요.

Error C2079 'apr_sockaddr_t::sin6' uses undefined struct 'sockaddr_in6' mod_aspdotnet   e:\git_clone\mod_aspdotnet\trunk\apache2_4_include\apr_network_io.h 269 

mod_aspdotnet.cpp 파일에 ws2tcpip 헤더 파일을 추가하는 것으로 해결했습니다.

#include <ws2tcpip.h>

위의 작업까지만 해주면 일단 Apache 2.4 지원을 위한 마이그레이션은 대충 완료됩니다.




문제는, Visual Studio 2017에서 빌드하는 경우 C++/CLI 프로젝트의 어셈블리가 .NET 4.0에 의존성을 갖는다는 점입니다. 이 때문에 Apache.Web.dll이 .NET 2.0 GAC가 아니라 .NET 4.0 GAC에 등록됩니다.

따라서, Apache 2.4에서 .NET 2.0~3.5용의 ASP.NET을 구동하는 경우 crash가 발생하는데 디버깅을 해 보니 다음의 라인에서 발생합니다.

static apr_status_t asp_net_stop(void *dummy)
{
    global_conf->pHostFactory->Destroy(); // pHostFactory == nullptr

    if (global_conf->pHostFactory) {

        global_conf->pHostFactory->Release();
    }
    if (global_conf->pCorRuntime) {
        global_conf->pCorRuntime->Stop();
        global_conf->pCorRuntime->Release();
    }

    // ...[생략]...
}

이 상태에서 아파치 에러 로그(\xampp\apache\logs)는 다음과 같이 보여줍니다.

[Wed Aug 30 17:14:16.117970 2017] [core:notice] [pid 16020:tid 544] mod_aspdotnet: CorBindToRuntimeEx has loaded version v2.0.50727 of the .NET CLR engine.
ed Aug 30 17:16:00.679504 2017] [core:error] [pid 1764:tid 584] (-2146304894)Unknown error: mod_aspdotnet: Could not create the .NET interface for the Apache.Web.HostFactory.
[Wed Aug 30 17:16:00.679504 2017] [core:crit] [pid 1764:tid 584] (-2146304894)Unknown error: mod_aspdotnet: Failed to start Asp.Net Apache.Web host factory
AH00016: Configuration Failed

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Apache.Web, Version=2.4.0.2199, Culture=neutral, PublicKeyToken=9b9b842f49b86351' or one of its dependencies. The system cannot find the file specified.
File name: 'Apache.Web, Version=2.4.0.2199, Culture=neutral, PublicKeyToken=9b9b842f49b86351'
   at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
   at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(String assemblyName, String typeName)
   at System.AppDomain.CreateInstance(String assemblyName, String typeName)

위의 오류를 해결하기 위해 CLR 4를 로드하도록 변경했고 하위 호환성으로 .NET 2.0~3.5용의 ASP.NET이 동작하게 되어 있습니다.

단지, 현재 .NET 2.0~3.5만 설치된 환경에서 ASP.NET을 Apache 2.4에서 구동하는 방법은 없습니다. 만약 원한다면 Visual Studio 2008 설치 후 소스코드를 빌드하시면 됩니다.




위의 작업을 모두 마치고 나면 바이너리에 대한 마이그레이션은 전부 끝나지만 아쉽게도 httpd.conf에 대한 변경 사항이 Apache 2.4에서 달라진 것이 있어 기존의 mod_aspdotnet 사용 방법의 문서대로 하면 다음과 같은 오류가 발생합니다.

[Thu Aug 31 11:22:44.772053 2017] [authz_core:error] [pid 22704:tid 2724] [client ::1:63160] AH01630: client denied by server configuration: C:/temp/xampp/aspdocs/test.aspx

웹 브라우저 화면에는 이런 메시지가 뜹니다.

접근이 거부됨!

요청한 객체에 접근할 수 있는 권한이 없습니다. 읽기 보호가 되어 있거나 웹서버가 읽을 수 없도록 되어 있습니다. 

만약 이것이 서버 오류라고 생각되면, 웹 관리자에게 연락하시기 바랍니다. 

Error 403

localhost
Apache/2.4.27 (Win32) OpenSSL/1.0.2l PHP/7.1.8 mod_aspdotnet/2.4 

문제는 다음의 설정이었는데,

    <Directory "c:/temp/xampp/aspdocs">
    Options FollowSymlinks ExecCGI
    Order allow,deny
    Allow from all
    DirectoryIndex index.htm index.aspx index.asp
    </Directory>

아래의 문서에 보면 2.4에서 바뀌었다고 합니다.

Client denied by server configuration
; https://wiki.apache.org/httpd/ClientDeniedByServerConfiguration

따라서, mod_aspdotnet for Apache 2.4의 경우 다음과 같은 식으로 .conf 파일을 변경해야 합니다.

LoadModule aspdotnet_module modules/mod_aspdotnet.so
AddHandler asp.net asax ascx ashx asmx aspx axd config cs csproj licx rem resources resx soap vb vbproj vsdisco webinfo

<IfModule mod_aspdotnet.cpp>
    AspNetMount /aspdocs "c:/temp/xampp/aspdocs"
    Alias /aspdocs "c:/temp/xampp/aspdocs"

    <Directory "c:/temp/xampp/aspdocs">
Require all granted
    </Directory>

    AliasMatch /aspnet_client/system_web/(\d+)_(\d+)_(\d+)_(\d+)/(.*) "C:/Windows/Microsoft.NET/Framework/v$1.$2.$3/ASP.NETClientFiles/$4"

    <Directory "C:/Windows/Microsoft.NET/Framework/v*/ASP.NETClientFiles">
    Options FollowSymlinks
    Order allow,deny
    Allow from all
    </Directory>

</IfModule>




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 9/4/2017]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... [106]  107  108  109  110  111  112  113  114  115  116  117  118  119  120  ...
NoWriterDateCnt.TitleFile(s)
11273정성태8/22/201721624오류 유형: 415. 윈도우 업데이트 에러 Error 0x80070643
11272정성태8/21/201724745VS.NET IDE: 120. 비주얼 스튜디오 2017 버전 15.3.1 - C# 7.1 공개 [2]
11271정성태8/19/201719166VS.NET IDE: 119. Visual Studio 2017에서 .NET Core 2.0 프로젝트 환경 구성하는 방법
11270정성태8/17/201730606.NET Framework: 673. C#에서 enum을 boxing 없이 int로 변환하기 [2]
11269정성태8/17/201721414디버깅 기술: 93. windbg - 풀 덤프에서 .NET 스레드의 상태를 알아내는 방법
11268정성태8/14/201720991디버깅 기술: 92. windbg - C# Monitor Lock을 획득하고 있는 스레드 찾는 방법
11267정성태8/10/201725074.NET Framework: 672. 모노 개발 환경
11266정성태8/10/201724862.NET Framework: 671. C# 6.0 이상의 소스 코드를 Visual Studio 설치 없이 명령행에서 컴파일하는 방법
11265정성태8/10/201753124기타: 66. 도서: 시작하세요! C# 7.1 프로그래밍: 기본 문법부터 실전 예제까지 [11]
11264정성태8/9/201724000오류 유형: 414. UWP app을 signtool.exe로 서명 시 0x8007000b 오류 발생
11263정성태8/9/201719471오류 유형: 413. The C# project "..." is targeting ".NETFramework, Version=v4.0", which is not installed on this machine. [3]
11262정성태8/5/201718203오류 유형: 412. windbg - SOS does not support the current target architecture. [3]
11261정성태8/4/201720775디버깅 기술: 91. windbg - 풀 덤프 파일로부터 강력한 이름의 어셈블리 추출 후 사용하는 방법
11260정성태8/3/201718868.NET Framework: 670. C# - 실행 파일로부터 공개키를 추출하는 방법
11259정성태8/2/201718128.NET Framework: 669. 지연 서명된 어셈블리를 sn.exe -Vr 등록 없이 사용하는 방법
11258정성태8/1/201718892.NET Framework: 668. 지연 서명된 DLL과 서명된 DLL의 차이점파일 다운로드1
11257정성태7/31/201719128.NET Framework: 667. bypassTrustedAppStrongNames 옵션 설명파일 다운로드1
11256정성태7/25/201720580디버깅 기술: 90. windbg의 lm 명령으로 보이지 않는 .NET 4.0 ClassLibrary를 명시적으로 로드하는 방법 [1]
11255정성태7/18/201723161디버깅 기술: 89. Win32 Debug CRT Heap Internals의 0xBAADF00D 표시 재현 [1]파일 다운로드3
11254정성태7/17/201719475개발 환경 구성: 322. "Visual Studio Emulator for Android" 에뮬레이터를 "Android Studio"와 함께 쓰는 방법
11253정성태7/17/201719740Math: 21. "Coding the Matrix" 문제 2.5.1 풀이 [1]파일 다운로드1
11252정성태7/13/201718413오류 유형: 411. RTVS 또는 PTVS 실행 시 Could not load type 'Microsoft.VisualStudio.InteractiveWindow.Shell.IVsInteractiveWindowFactory2'
11251정성태7/13/201717062디버깅 기술: 88. windbg 분석 - webengine4.dll의 MgdExplicitFlush에서 발생한 System.AccessViolationException의 crash 문제 (2)
11250정성태7/13/201720662디버깅 기술: 87. windbg 분석 - webengine4.dll의 MgdExplicitFlush에서 발생한 System.AccessViolationException의 crash 문제 [1]
11249정성태7/12/201718453오류 유형: 410. LoadLibrary("[...].dll") failed - The specified procedure could not be found.
11248정성태7/12/201724904오류 유형: 409. pip install pefile - 'cp949' codec can't decode byte 0xe2 in position 208687: illegal multibyte sequence
... [106]  107  108  109  110  111  112  113  114  115  116  117  118  119  120  ...