tamuraです。
Dexadorを認証プロキシに対応させた内容です。 プロキシには対応しているのですが、プロキシサーバがユーザ/パスワードを必要とした時にも対応させました。
(dex:get "https://www.yahoo.co.jp"
:proxy "http://proxyuser:proxypass@proxyserver:8081")
この形式で認証プロキシを通すことができます。
認証プロキシ対応
HTTP
HTTPの場合は超簡単です。
リクエストヘッダに Proxy-Authorization
パラメータを設定するだけです。
1 file changed, 7 insertions(+)
src/backend/usocket.lisp | 7 +++++++
modified src/backend/usocket.lisp
@@ -499,6 +499,13 @@
(format nil "~A:~A"
(car basic-auth)
(cdr basic-auth))))))
+ (when proxy
+ (let* ((uri (quri:uri proxy))
+ (proxy-auth (quri:uri-userinfo uri)))
+ (when proxy-auth
+ (write-header* :proxy-authorization
+ (format nil "Basic ~A"
+ (string-to-base64-string proxy-auth))))))
(cond
(multipart-p
(write-header* :content-type (format nil "multipart/form-data; boundary=~A" boundary))
quri
を使ってURLにユーザ名とパスワードを仕込んでいます。
HTTPS
HTTPSでちょっとハマりました。
HTTPヘッダではなく、CONNECT
のタイミングでProxy-Authorization
を入れる必要があるとのことでした。
2 files changed, 21 insertions(+), 10 deletions(-)
src/backend/usocket.lisp | 24 +++++++++++++++---------
src/util.lisp | 7 ++++++-
modified src/backend/usocket.lisp
@@ -361,14 +361,20 @@
buffer)
(fast-write-sequence +crlf+ buffer)))))
-(defun make-connect-stream (uri version stream)
+(defun make-connect-stream (uri version stream &optional proxy-auth)
(let ((header (with-fast-output (buffer)
- (write-connect-header uri version buffer))))
+ (write-connect-header uri version buffer proxy-auth))))
(write-sequence header stream)
(force-output stream)
(read-until-crlf*2 stream)
stream))
+(defun make-proxy-authorization (uri)
+ (let ((proxy-auth (quri:uri-userinfo uri)))
+ (when proxy-auth
+ (format nil "Basic ~A"
+ (string-to-base64-string proxy-auth)))))
+
(defun-careful request (uri &rest args
&key (method :get) (version 1.1)
content headers
@@ -416,7 +422,7 @@
(t :default)))))
(cl+ssl:with-global-context (ctx :auto-free-p t)
(cl+ssl:make-ssl-client-stream (if proxy
- (make-connect-stream uri version stream)
+ (make-connect-stream uri version stream (make-proxy-authorization con-uri))
stream)
:hostname (uri-host uri)
:verify (not insecure)
@@ -500,12 +506,12 @@
(car basic-auth)
(cdr basic-auth))))))
(when proxy
- (let* ((uri (quri:uri proxy))
- (proxy-auth (quri:uri-userinfo uri)))
- (when proxy-auth
- (write-header* :proxy-authorization
- (format nil "Basic ~A"
- (string-to-base64-string proxy-auth))))))
+ (let ((scheme (quri:uri-scheme uri)))
+ (when (string= scheme "http")
+ (let* ((uri (quri:uri proxy))
+ (proxy-authorization (make-proxy-authorization uri)))
+ (when proxy-authorization
+ (write-header* :proxy-authorization proxy-authorization))))))
(cond
(multipart-p
(write-header* :content-type (format nil "multipart/form-data; boundary=~A" boundary))
modified src/util.lisp
@@ -141,7 +141,7 @@
(let ((*header-buffer* ,buffer))
,@body)))
-(defun write-connect-header (uri version buffer)
+(defun write-connect-header (uri version buffer &optional proxy-auth)
(fast-write-sequence (ascii-string-to-octets "CONNECT") buffer)
(fast-write-byte #.(char-code #\Space) buffer)
(fast-write-sequence (ascii-string-to-octets (format nil "~A:~A"
@@ -160,6 +160,11 @@
(uri-host uri)
(uri-port uri)))
buffer)
+ (when proxy-auth
+ (fast-write-sequence +crlf+ buffer)
+ (fast-write-sequence (ascii-string-to-octets "Proxy-Authorization:") buffer)
+ (fast-write-byte #.(char-code #\Space) buffer)
+ (fast-write-sequence (ascii-string-to-octets proxy-auth) buffer))
(fast-write-sequence +crlf+ buffer)
(fast-write-sequence +crlf+ buffer))
テスト
手元でのテストでもいいんですが、travis-ciでテストしたいな〜と思いいろいろやっていたら2ヶ月くらいたってしまいました。
squid
squidでhttpsを通すproxyを作ります。
http_access allow all
http_port 8081
auth_param basic program /usr/lib/squid3/basic_ncsa_auth /home/travis/squid-passwd
auth_param basic children 5
auth_param basic realm Squid proxy-caching web server
auth_param basic credentialsttl 2 hours
acl basic_nsa proxy_auth REQUIRED
http_access allow basic_nsa
nginx
nginxでhttpsを喋るサーバを作ります。
events {
worker_connections 1024;
}
http {
include /home/travis/nginx/conf/mime.types;
access_log off;
server {
listen 5000;
listen 5001 ssl;
server_name localhost;
ssl_certificate /home/travis/server.crt;
ssl_certificate_key /home/travis/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /home/travis/benchmark/;
}
}
}
travis
travis上でsquidを使ってproxyサーバを立てます。
:install
.. 省略 ..
# proxy
- openssl req -x509 -nodes -new -keyout $HOME/server.key -out $HOME/server.crt -days 365 -subj "/C=JP/ST=Tokyo/L=Shinagawa/O=test/OU=test/CN=dexador"
- sudo apt-get -qq update
- sudo apt-get -qq install squid3 apache2-utils
- htpasswd -b -c $HOME/squid-passwd testuser testpass
before_script:
- nginx -c "$TRAVIS_BUILD_DIR/t/nginx-proxy.conf" -p "$HOME/nginx"
- sudo squid3 -f "$TRAVIS_BUILD_DIR/t/squid.conf"
- sudo squid3 -f "$TRAVIS_BUILD_DIR/t/squid-auth.conf"
- ros --version
- ros config
- cp -R $TRAVIS_BUILD_DIR/benchmark $HOME
テスト
proxyサーバとHTTPサーバ・HTTPSサーバを定義してテストします。
(defparameter *AUTH-PROXY* "http://testuser:testpass@localhost:8081")
(defparameter *HTTP* "http://localhost:5000/181B.html")
(defparameter *HTTPS* "https://localhost:5001/181B.html")
(subtest "HTTP with auth proxy"
(subtest "GET"
(multiple-value-bind (body code headers)
(dex:get *HTTP*
:proxy *AUTH-PROXY*)
(is code 200)
(is body BODY)
(is (gethash "content-length" headers) 181))))
(subtest "HTTPS with auth proxy"
(subtest "GET"
(multiple-value-bind (body code headers)
(dex:get *HTTPS*
:proxy *AUTH-PROXY*
:insecure T)
(is code 200)
(is body BODY)
(is (gethash "content-length" headers) 181))))
いかのとおり、テストOKです!
最後に
https://github.com/fukamachi/dexador/pull/58/files
マージしていただきました。