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

비밀번호

댓글 작성자
 




1  2  3  [4]  5  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13722정성태9/2/20241725C/C++: 169. C/C++ - CRT(C Runtime) 함수에 의존성이 없는 프로젝트 생성
13721정성태8/30/20242127C/C++: 168. Visual C++ CRT(C Runtime DLL: msvcr...dll)에 대한 의존성 제거 - 두 번째 이야기
13720정성태8/29/20241976VS.NET IDE: 193. C# - Visual Studio의 자식 프로세스 디버깅
13719정성태8/28/20242258Linux: 79. C++ - pthread_mutexattr_destroy가 없다면 메모리 누수가 발생할까요?
13718정성태8/27/20242753오류 유형: 921. Visual C++ - error C1083: Cannot open include file: 'float.h': No such file or directory [2]
13717정성태8/26/20242417VS.NET IDE: 192. Visual Studio 2022 - Windows XP / 2003용 C/C++ 프로젝트 빌드
13716정성태8/21/20242210C/C++: 167. Visual C++ - 윈도우 환경에서 _execv 동작
13715정성태8/19/20242098Linux: 78. 리눅스 C/C++ - 특정 버전의 glibc 빌드 (docker-glibc-builder)
13714정성태8/19/20242431닷넷: 2295. C# 12 - 기본 생성자(Primary constructors) (책 오타 수정) [3]
13713정성태8/16/20242642개발 환경 구성: 721. WSL 2에서의 Hyper-V Socket 연동
13712정성태8/14/20242708개발 환경 구성: 720. Synology NAS - docker 원격 제어를 위한 TCP 바인딩 추가
13711정성태8/13/20243188Linux: 77. C# / Linux - zombie process (defunct process)파일 다운로드1
13710정성태8/8/20243286닷넷: 2294. C# 13 - (6) iterator 또는 비동기 메서드에서 ref와 unsafe 사용을 부분적으로 허용파일 다운로드1
13709정성태8/7/20243165닷넷: 2293. C# - safe/unsafe 문맥에 대한 C# 13의 (하위 호환을 깨는) 변화파일 다운로드1
13708정성태8/7/20242784개발 환경 구성: 719. ffmpeg / YoutubeExplode - mp4 동영상 파일로부터 Audio 파일 추출
13707정성태8/6/20243228닷넷: 2292. C# - 자식 프로세스의 출력이 4,096보다 많은 경우 Process.WaitForExit 호출 시 hang 현상파일 다운로드1
13706정성태8/5/20243591개발 환경 구성: 718. Hyper-V - 리눅스 VM에 새로운 디스크 추가
13705정성태8/4/20243594닷넷: 2291. C# 13 - (5) params 인자 타입으로 컬렉션 허용파일 다운로드1
13704정성태8/2/20243359닷넷: 2290. C# - 간이 dotnet-dump 프로그램 만들기파일 다운로드1
13703정성태8/1/20243670닷넷: 2289. "dotnet-dump ps" 명령어가 닷넷 프로세스를 찾는 방법
13702정성태7/31/20243600닷넷: 2288. Collection 식을 지원하는 사용자 정의 타입을 CollectionBuilder 특성으로 성능 보완파일 다운로드1
13701정성태7/30/20243606닷넷: 2287. C# 13 - (4) Indexer를 이용한 개체 초기화 구문에서 System.Index 연산자 허용파일 다운로드1
13700정성태7/29/20243309디버깅 기술: 200. DLL Export/Import의 Hint 의미
13699정성태7/27/20243447닷넷: 2286. C# 13 - (3) Monitor를 대체할 Lock 타입파일 다운로드1
13698정성태7/27/20243371닷넷: 2285. C# - async 메서드에서의 System.Threading.Lock 잠금 처리파일 다운로드1
13697정성태7/26/20243505닷넷: 2284. C# - async 메서드에서의 lock/Monitor.Enter/Exit 잠금 처리파일 다운로드1
1  2  3  [4]  5  6  7  8  9  10  11  12  13  14  15  ...