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

비밀번호

댓글 작성자
 




... 121  122  123  124  125  126  127  128  129  130  131  132  133  134  [135]  ...
NoWriterDateCnt.TitleFile(s)
1679정성태5/31/201420413.NET Framework: 438. .NET CLR2 보안 모델에서의 APTCA 역할파일 다운로드1
1678정성태5/31/201424129개발 환경 구성: 222. 라이브러리 개발자를 위한 보안 권한 테스트 - "Network Service" 계정 권한으로 실행
1677정성태5/30/201419718VS.NET IDE: 87. IIS Express - 웹 응용 프로그램의 .NET 버전에 맞는 CLR이 로드되지 않는 경우파일 다운로드1
1676정성태5/27/201427775Windows: 95. 윈도우 8에서 Hyper-V 유무에 따른 듀얼 부트 설정하는 방법 [1]
1675정성태5/27/201429937Windows: 94. 윈도우 8.1에서 윈도우 체험 지수(Windows Experience Index, WEI) 확인 방법
1674정성태5/24/201423554VS.NET IDE: 86. 하나의 T4 템플릿으로 여러 개의 소스코드 파일을 자동으로 생성하는 방법 [1]파일 다운로드1
1673정성태5/19/201423074.NET Framework: 437. WACOM 태블릿 환경에서 WinForm 실행시 System.ArgumentException 예외 발생
1672정성태5/15/201423580기타: 46. Microsoft의 응용 프로그램을 클라우드로 제공하는 서비스 - Azure RemoteApp 소개 [2]
1671정성태5/15/201424197.NET Framework: 436. XNA Content 리소스의 해제 후 다시 로드해서 사용하면 ObjectDisposedException 예외 발생 [2]
1670정성태5/15/201424499.NET Framework: 435. .NET GC - 하위 세대의 객체를 포함하는 상위 세대의 참조를 추적하기 위한 card-table
1669정성태5/15/201444518Windows: 93. 윈도우 시스템 디스크 용량 확보를 위한 $PatchCache$ 폴더 삭제 [2]
1668정성태5/10/201423783.NET Framework: 434. Microsoft.SqlServer.Types.SqlGeography 형변환 시 null 반환하는 문제
1667정성태5/5/201424555개발 환경 구성: 221. Azure 데이터베이스를 로컬 DB로 이전하는 방법 [2]
1666정성태5/2/201441256기타: 45. 윈도우 계정의 암호를 알아내는 mimikatz 도구 [5]
1665정성태5/1/201424764.NET Framework: 433. C# - 간단한 HyperLogLog 자료 구조 테스트파일 다운로드1
1664정성태4/28/201422126오류 유형: 227. Process Explorer의 프로세스 뷰가 트리 형식으로 보이지 않는 문제
1663정성태4/28/201418578오류 유형: 226. Visual Studio - We were unable to establish the connection because it is configured for user
1662정성태4/28/201423164개발 환경 구성: 220. supportedRuntime 설정을 위한 app.config Transformation [1]
1661정성태4/26/201419922.NET Framework: 432. WPF - System.Windows.Data Error: 47 : XmlDataProvider has inline XML that does not explicitly set its XmlNamespace (xmlns="").
1660정성태4/25/201427599VC++: 77. C++ 숫자형 값이 범위를 벗어나는 경우의 출력 사례 모음
1659정성태4/17/201427602.NET Framework: 431. .NET EXE 파일을 닷넷 프레임워크 버전에 상관없이 실행할 수 있을까요? [5]
1658정성태4/17/201419710.NET Framework: 430. C#에서 사용자 정의 예약어가 가능할까요? [1]
1657정성태4/10/201439776.NET Framework: 429. C# - 유니코드 한글 문자열을 ks_c_5601-1987로 변환하는 방법 [3]파일 다운로드1
1656정성태3/19/201422944오류 유형: 225. regsvcs 등록 시 0x80040153 오류
1655정성태3/19/201423113Windows: 92. Thumbs.db 파일이 삭제 안 되는 문제
1654정성태3/19/201425204개발 환경 구성: 219. SOS.dll 확장 모듈을 버전 별로 구하는 방법 [4]
... 121  122  123  124  125  126  127  128  129  130  131  132  133  134  [135]  ...