apache Proxy 설정 정리 - Kim-Taesu/study GitHub Wiki
- 클라이언트나 로컬 기기(일반적으로 컴퓨터나 모바일기기)에서 서버나 원격 호스트(이하 서버)로 보내지는(전송되는) 데이터 또는 보내는 것을 의미한다
- 업스트림의 반대로, 서버에서 로컬 기기로 전송되는 데이터의 흐름을 말한다.
- 신뢰할 수 있는 서버가 아닌 이상 proxy 설정을 하지 않는 것을 권장
-
mod_proxy
및 관련 모듈은 Apache HTTP Server용 프록시/게이트웨이를 구현하여 여러 유명한 프로토콜과 다양한 로드밸런싱 알고리즘을 지원한다.- 서드파티 모듈도 추가할 수 있다.
- 해당 모듈을 사용하기 위해 우선 Apache 서버에 모듈을 로드해야 한다.
- 빌드 시 정적으로 포함되거나
-
LoadModule
지시문을 통해 동적으로 포함될 수 있다.
- 필수 포함 목록
-
mod_proxy
: 기본 proxy 기능 제공 -
로드 밸런싱이 필요한 경우,
mod_proxy_balancer
또는 1개 이상의 밸런서가 필요하다. -
1개 이상의 scheme 또는 protocol, modules 필요
Protocol Module AJP13 (Apache JServe Protocol version 1.3) mod_proxy_ajp CONNECT (for SSL) mod_proxy_connect FastCGI mod_proxy_fcgi ftp mod_proxy_ftp HTTP/0.9, HTTP/1.0, and HTTP/1.1 mod_proxy_http HTTP/2.0 mod_proxy_http2 SCGI mod_proxy_scgi UWSGI mod_proxy_uwsgi WS and WSS (Web-sockets) mod_proxy_wstunnel
-
- 추가 확장 기능은 다른 모듈에서 제공된다.
-
mod_cache
: 캐싱 관련 -
mod_ssl
: SSL/TLS 프로토콜을 사용하여 원격 서버에 접속하는 기능
-
- Apache HTTP Server는 총 2가지(포워드 프록시, 리버스 프록시) 모드로 구성할 수 있다.
- 클라이언트와 원본 서버 사이에 있는 중간 서버이다.
- 원본 서버로부터 컨텐츠를 가져오기 위해 클라이언트는 원본 서버를 대상으로 하는 요청을 프록시 서버로 보낸다.
- 프록시 서버는 원본 서버에 콘텐츠를 요청하고 클라이언트에게 반환한다.
- 클라이언트는 반드시 포워드 프록시를 사용하여 다른 사이트(원본서버)에 접근하도록 구성되어야 한다.
- 일반적인 사용 : 방화벽에 의해 제한되는 내부 클라이언트에 접근할 때 사용
- 캐싱(
mod_cache
)을 사용하여 네트워크 사용량을 줄일 수 있다. - 포워드 프록시는
ProxyRequests
지시문을 통해 활성화 된다. - 포워드 프록시를 사용하면 클라이언트가 프록시 서버를 통해 임의의 사이트에 접근하고, 클라이언트에 대한 정보를 숨길 수 있다.
- 따라서 포워드 프록시를 활성화하기 전에 승인된 클라이언트만 프록시 서버에 접근할 수 있도록 해야한다.
- 일반 웹 서버처럼 클라이언트에 나타난다.
- 클라이언트는 리버스 프록시의 콘텐츠에 대해 요청을 하게되면, 리버스 프록시 서버는 해당 요청을 원본 서버로 보낸다. 이후 리버스 프록시 서버가 마치 원본 서버인 것 처럼 컨텐츠를 클라이언트에게 반환한다.
- 일반적인 사용 : 인터넷 사용자가 방화벽 뒤에 있는 서버에 대한 액세스를 제공할 때 사용
- 리버스 프록시를 사용하여 여러 백엔드 서버 간으 ㅣ로드 균형을 조정하거나 느린 백엔드 서버에 캐싱을 제공할 수 있다.
- 리버스 프록시를 사용하여 여러 서버를 동일한 1개의 URL로 가져올 수도 있다.
- 리버스 프록시는
ProxyPass
지시문 또는RewriteRule
지시문에 대한[P]
flag를 사용하여 활성화 된다. - 리버스 프록시를 구성하기 위해
ProxyRequests
를 활성화 할 필요는 없다.
ProxyPass "/foo" "http://foo.example.com/bar"
ProxyPassReverse "/foo" "http://foo.example.com/bar"
ProxyRequests On
ProxyVia On
<Proxy "*">
Require host internal.example.com
</Proxy>
- 핸들러를 추가하여 리버스 프록시 요청으로 처리하도록 강제할 수 있다.
# 리버스 프록시를 사용하여, PHP 스크립트에 대한 모든 요청을 지정된 FastCGI 서버로 전달한다.
<FilesMatch "\.php$">
# Unix sockets require 2.4.7 or later
SetHandler "proxy:unix:/path/to/app.sock|fcgi://localhost/"
</FilesMatch>
-
프록시는
worker
라 불리는 object에서 원본 서버와의 통신 설정과 통신 파라미터를 관리한다. -
기본 제공되는
worker
는 2개이다.- 포워드 프록시 worker (
default
) - 리버스 프록시 worker
- 포워드 프록시 worker (
-
추가
worker
는 설정파일에 명시적으로 기술하면 된다. -
2개의 기본
worker
는 설정이 고정되어 있고 특정 요청과 일치하는 다른 worker가 없는 경우 사용된다.- HTTP Keep-Alive 또는 connection 재사용을 사용하지 않는다.
- 각 요청에 대해 원본 서버에 대한 TCP 연결이 open/close 된다.
-
설정파일에 명시적으로 기술한
worker
는 URL로 식별된다.- 일반적으로 리버스 프록시에 사용될 때
ProxyPass
또는ProxyPassMatch
를 사용하여 생성 및 설정한다.
- 일반적으로 리버스 프록시에 사용될 때
-
예시
-
/example
로 요청이 프록시 서버로 들어오면 connectiontimeout=5, timeout=30 설정 값을 사용하는 원본 서버 URL("http://backend.example.com"
)과 연결된 worker가 생성된다.
ProxyPass "/example" "http://backend.example.com" connectiontimeout=5 timeout=30
- 포워드 프록시에서 사용되는 경우
worker
는 일반저긍로ProxySet
지시문을 통해 정의된다.
ProxySet "http://backend.example.com" connectiontimeout=5 timeout=30
<Proxy "http://backend.example.com"> ProxySet connectiontimeout=5 timeout=30 </Proxy>
-
-
보통 포워드 프록시는 일반적으로 다양한 원본 서버와 통신하기 때문에, 특정 원본서버로 보내도록 설정한
worker
를 사용하지 않는다.- 특정 원본 서버에 대해 요청량이 많을 경우 사용할 수 있다.
-
설정 파일에 명시적으로 설정한
worker
는 포워드/리버스 프록시 개념이 없다.- 원본 서버와의 통신에 대한 공통 개념을 캡슐화 한다.
-
리버스 프록시에서 사용하기 위한
worker
(ProxyPass
로 생성 된)는 원본 서버에 대한 URL이worker
에 설정한 URL과 일치/불일치할 때 포워드 프록시 요청으로도 사용될 수 있다.
예시
ProxyPass "/examples" "http://backend.example.com/examples"
ProxyPass "/docs" "http://backend.example.com/docs"
- 위 예시는 총 2개의
worker
가 정의되어 있다.- 각
worker
는 별도의 connection pool과 설정을 가지고 있다.
- 각
-
worker
URL이 겹치는 경우 Worker Sharing이 발생한다. -
worker
의 URL이 설정파일에서 다른worker
URL의 하위 계층일 경우 발생
ProxyPass "/apps" "http://backend.example.com/" timeout=60
ProxyPass "/examples" "http://backend.example.com/examples" timeout=10
- 위 예시에서 두 번째
worker
는 실제로 생성되지 않는다.- 첫 번째
worker
로 사용된다.
- 첫 번째
- 따라서 connection pool이 1개만 존재하므로 connection이 더 자주 재사용된다.
- 명시적으로 기입한 두 번째
worker
의 설정은 무시되며 warning 로그가 남는다.- 위 예시에서
/examples
요청에 대한 timeout은 10대신 60으로 설정된다.
- 위 예시에서
- worker sharing을 방지하려면 가장 긴
worker
URL이 가장 상단에 오도록 정렬해야한다. - 반대로 worker sharing을 최대로 사용하려면 URL 길이 역순으로 정렬하면 된다.
- 명시적으로 설정한
worker
는 2가지 유형이 있다.direct worker
(load) balancer worker
- 2가지 유형 모두
ProxyPass
지시문의 속성을 사용하여 중요한 설정을 할수 있다.-
ProxySet
을 사용하여ProxyPass
와 동일한 속성을 설정할 수 있다.
-
direct worker
- 사용할 수 있는 옵션은 원본 서버 URL에 지정된 프로토콜에 따라 다르다.
- 사용가능한 프로토콜은
ajp
,fcgi
,ftp
,http
및scgi
가 포함된다.
balancer worker
- 실제로 요청을 처리하기 위해 direct worker를 사용하는 가상의 worker
- 각 밸런서는 여러 direct worker를 가질 수 있다.
- 요청을 처리할 때 구성된 로드 밸런싱 알고리즘을 기반으로 worker를 선택한다.
- worker URL이 밸런서를 프로토콜로 사용하는 경우 밸런서 worker가 생성된다.
- 밸런서 url은 밸런서 worker를 고유하게 식별한다.
- direct worker는
BalancerMember
를 사용하여 밸런서에 추가된다.
-
<Proxy>
블록으로 proxy 접근을 설정할 수 있다.
<Proxy "*">
Require ip 192.168.0
</Proxy>
- 포워드 프록시(
ProxyRequests
지시문 사용)를 사용하는 경우 프록서 서버로의 접근을 엄격하게 제한해야 한다.- 모든 클라이언트가 프록시 서버를 사용하여 클라이언트 IP를 숨기고 임의의 원본서버에 접근할 수 있기 때문이다.
- 리버스 프록시(
ProxtRequests
가Off
+ProxyPass
지시문 사용)를 사용하는 경우 클라이언트는 특별히 설정한 원본 서버에만 연결할 수 있으므로 프록시 서버에 대한 접근 제어는 덜 중요하다.
-
ProxyBlock
지시문을 사용하는 경우, hostname의 IP는 프록시 서버에서 일치 여부를 테스트할 때 조회되고 캐싱된다. - hostname을 찾는 동안 몇 초의 시간이 소요될 수 있다.
- 인트라넷에 위치한 Apache HTTP 프록시 서버는 회사의 방화벽을 통해 외부 요청을 전달해야 한다.
-
ProxyRemote
지시문을 사용하여 개별scheme
를 회사 방화벽 프록시에 전달하도록 설정
-
- 인트라넷 내부 리소스에 접근해야 하는 경우, 호스트에 접근할 때 방화벽을 우회할 수 있다.
-
NoProxy
지시문을 사용하여, 인트라넷에 속하고 직접 액세스해야 하는 호스트를 지정하면 된다.
-
- 인트라넷 내부 사용자는 WWW 요청에서, 로컬 도메인 이름을 생략하는 경향이 있으므로
http://somehost.example.com/
요청 대신http://somehost/
를 요청한다.-
PromxyDomain
지시문을 사용하여 프록시 서버가 서비스용으로 구성된 경우, Apache httpd는 redirection 응답을 반환하고 클라이언트를 올바른 서버주소로 보낼 수 있다.
-
- POST와 같은 일부 요청에는 request body이 포함된다.
- HTTP 프로토콜은 request body을 포함하는 요청이 chunked transfer encoding을 사용하거나 요청 헤더에 Content-Length 헤더를 보내도록 요구한다.
- 이러한 요청을 원본 서버에 전달할 때
mod_proxy_http
는 항상 Content-Length 헤더 전송을 시도한다. - 그러나 request body 크기가 크고 원래 요청이 chunked encoding을 사용했다면 업스트림 요청에서도 chunked encoding을 사용할 수 있다.
- 환경 변수로 위 옵션을 제어할 수 있다.
-
proxy_sendcl
을 설정하면 항상 Content-Length 헤더를 전송하여 업스트림 서버와의 최대 호환성을 보장하고, -
proxy-sendchunked
를 설정하면 chunked encoding을 사용하여 리소스 사용을 최소화 한다.
- 이러한 요청을 원본 서버에 전달할 때
- 일부 상황에서 프록시 서버는 request body를 처리하기 위해 body 값을 디스크에 스풀링해야 한다.
- request body 원본 내용이 chunk encoding으로 전송되었지만, 원본 서버에서 request를 Content-Length 또는 HTTP/1.0으로 전송하도록 요청한 경우에 발생
- request body에 이미 Cotent-Length 헤더가 있지만 원본 서버가 들어오는 request body를 필터링하도록 구성된 경우에도 발생할 수 있다.
-
LimitRequestBody
는 프록시 서버가 디스크에 스풀링할 request body에만 적용된다.
chunked transfer encoding
- 클라이언트가 요청한 response 크기가 큰 경우 chunk 단위로 client에 전송한다.
- response 데이터 크기를 알 필요가 없다.
- 스트림 형태일 경우 유리
- response 헤더에
Content-Length
대신Transfer-Encoding:chunked
가 존재한다면 chunk 단위로 분할하여 데이터를 전송한다는 의미이다. - 받은 chunk 단위 데이터의 크기가 0일 때 모든 데이터를 전송했다는 의미이다.
- 리버스 프록시를 사용할 때
mod_proxy_http
는 추가 정보를 원본 서버에 전달하기 위해 여러 request 헤더를 추가한다.
헤더 | 설명 |
---|---|
X-Forwarded-For |
클라이언트의 IP 주소 |
X-Forwarded-Host |
클라이언트가 요청한 original host (proxy server) |
X-Forwarded-Server |
proxy server의 hostname 여러 프록시 서버를 거친 경우 1개 이상의 주소를 얻을 수 있다. |
- 커스텀 헤더를 추가하려면
RequestHeader
지시문을 사용하면 된다.
- 프록시가 적용된 지시문을 위한 컨테이너
예시
-
yournetwork.example.com
의 호스트만 프록시 서버를 통해 콘텐츠에 접근할 수 있도록 허용<Proxy "*"> Require host yournetwork.example.com </Proxy>
- 원격 서버(원본 서버)와 로컬 서버(프록시 서버) URL 매핑
- 로컬 서버는 일반적인 의미에서 프록시 역할을 하지 않지만 원격서버의 미러처럼 보인다.
- 로컬 서버는 종종 리버스 프록시 또는 게이트웨이라고 부른다.
-
ProxyPass
지시문의 path는 로컬 가상 경로의 이름이다. -
ProxyPass
지시문의 url은 원격 서버의 부분 URL이며 쿼리 문자열을 포함할 수 없다. -
ProxyRequests
지시문은 일반적으로ProxyPass
를 사용할 때 설정해야 한다.
내부에서 사용될 때
-
<Location>
섹션 안에서 사용될 때는 Location의 첫번 째 파라미터(URL)는 생략되고 로컬 디렉토리는 에서 가져온다. - 로컬 서버의 주소가
http://example.com/
이라고 가정
<Location "/mirror/foo/">
ProxyPass "http://backend.example.com/"
</Location>
-
http://example.com/mirror/foo/bar
에 대한 로컬 요청이 내부적으로http://backend.example.com/bar
에 대한 프록시 요청으로 변환된다. - 위 conf 설정은 아래와 같은 구문으로 대체가 가능하다.
- 하지만 해당 구문이 많이 존재할 경우 성능 저하가 발생할 수 있다.
ProxyPass "/mirror/foo/" "http://backend.example.com/"
- 첫 번째 아규먼트의 마지막이
/
로 끝나면 두 번째 아규먼트도/
로 끝나야한다.
!
지시문
-
!
지시문은 하위 디렉토리를 리버스 프록시하지 않으려는 경우에 사용
<Location "/mirror/foo/">
ProxyPass "http://backend.example.com/"
</Location>
<Location "/mirror/foo/i">
ProxyPass "!"
</Location>
ProxyPass "/mirror/foo/i" "!"
ProxyPass "/mirror/foo" "http://backend.example.com"
-
/mirror/foo/i
에 대한 요청을 제외하고/mirror/foo
에 대한 모든 요청을backend.example.com
에 프록시한다. -
ProxyPass 설정을 혼합하면 원하는대로 프록시가 안될 수 있다.
ProxyPass "/mirror/foo/i" "!"
<Location "/mirror/foo/">
ProxyPass "http://backend.example.com/"
</Location>
- Location 블록의
ProxyPass
지시문이 먼저 적용되기 때문에/mirror/foo/i
에 대한 요청이 프록시 처리된다. - 하나의
ProxyPass
지시문만 Location 블록에 배치할 수 있다.
- 리버스 프록시 서버에서 보낸 HTTP 응답 해더의 URL를 조정한다.
- Apache httpd가 HTTP redirect response에서
Location
,Content-Location
및 URI 헤더의 URL를 조정할 수 있도록 해준다. - Apache httpd를 리버스 프록시(또는 게이트웨이)로 사용하여 리버스 프록시 뒤에 남아 있는 원본 서버(백엔드 서버)의 HTTP redirect로 인해 리버스 프록시를 우회하는 것을 방지하는데 필요한 설정이다.
예시
- 프록시 서버의 주소가
http://example.com/
이라고 가정
ProxyPass "/mirror/foo/" "http://backend.example.com/"
ProxyPassReverse "/mirror/foo/" "http://backend.example.com/"
ProxyPassReverseCookieDomain "backend.example.com" "public.example.com"
ProxyPassReverseCookiePath "/" "/mirror/foo/"
-
http://example.com/mirror/foo/bar
에 대한 프록시 서버 요청이 내부적으로http://backend.example.com/bar
에 대한 프록시 요청으로 변환될 뿐만 아니라(ProxyPass가 여기에서 제공하는 기능). - 또한
http://backend.example.com/bar
를http://backend.example.com/quux
로 리디렉션할 때backend.example.com
서버가 보내는 리디렉션을 처리합니다. - Apache httpd는 HTTP redirect 응답을 클라이언트에 전달하기 전에 이를
http://example.com/mirror/foo/quux
로 조정한다. - URL 구성에 사용되는 호스트 이름은
UseCanonicalName
지시문 설정과 관련하여 선택됩니다.
- 프록시 요청에 수신 host HTTP 요청을 사용
- 해당 옵션이 활성화 되면 Host 헤더를 현재 사용자가 요청한 서버 host로 지정해준다.
- 일반적으로 해당 옵션은 Off 해야한다.
- 원본 서버(백엔드 서버)에서 원래 호스트 헤더를 평가해야 하는 경우 유용하다.