= ssl-forwardの接続元アドレス = riseに設置してあるHTTPSの透過プロキシssl-forwardは、pfと協調して外部の443番ポートへの通信を透過的にHTTPプロキシサーバに転送するプログラムである。 今まで接続元アドレスを指定していなかったためmma-gw-outではないアドレスで接続してしまっていた。 connect.cに丸投げしていたのだけれど、connect.cには接続元アドレスを指定する機能がない。 netcatであれば`-s`を与えることで接続元アドレスを指定できるのだが、こちらはHTTPプロキシを越える機能が無い。 一旦はncを用いて実装を試みたが、やはりssl-forward側で入出力双方向についてブロックせずに流し込んでやる必要があるようで 実相が面倒であった。 そこで方針を変えてconnect.cを改造することにした。netcat (`/usr/src/contrib/netcat/netcat.c`)を参考にした。 {{{#!highlight c start=568 /* Bind to a local port or source address if specified. */ if (sflag || pflag) { struct addrinfo ahints, *ares; /* try IP_BINDANY, but don't insist */ setsockopt(s, IPPROTO_IP, IP_BINDANY, &on, sizeof(on)); memset(&ahints, 0, sizeof(struct addrinfo)); ahints.ai_family = res0->ai_family; ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; ahints.ai_flags = AI_PASSIVE; if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) errx(1, "getaddrinfo: %s", gai_strerror(error)); if (bind(s, (struct sockaddr *)ares->ai_addr, ares->ai_addrlen) < 0) errx(1, "bind failed: %s", strerror(errno)); freeaddrinfo(ares); } }}} なるほど、`listen`するときと同様に`bind`すればいいのか。 そういうわけで、`connect.c`の接続部分を改造した。 {{{#!highlight diff diff --git a/connect.c b/connect.c index f574711..5d57868 100644 --- a/connect.c +++ b/connect.c @@ -301,6 +301,7 @@ const char *dotdigits = "0123456789."; /* options */ int f_debug = 0; +char *source_addr = NULL; /* option 'A' */ /* report flag to hide secure information */ int f_report = 1; @@ -1608,6 +1609,16 @@ getarg( int argc, char **argv ) } break; + case 'A': + if ( 1 < argc ) { + argv++, argc--; + source_addr = *argv; + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; + case 'V': /* print version */ fprintf(stderr, "%s\nVersion %s\n", progdesc, revstr); exit(0); @@ -1784,6 +1795,23 @@ open_connection( const char *host, u_short port ) debug("connecting to %s:%u\n", inet_ntoa(saddr.sin_addr), port); s = socket( AF_INET, SOCK_STREAM, 0 ); + + if ( source_addr ) { + int error; + struct addrinfo hints, *res; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + error = getaddrinfo(source_addr, NULL, &hints, &res); + if ( error ) + debug( "getaddrinfo() failed: %s\n", strerror(error)); + if ( bind( s, (struct sockaddr *)res->ai_addr, res->ai_addrlen ) < 0) + debug( "bind() failed: %s\n", strerror(errno)); + freeaddrinfo(res); + } + if ( connect( s, (struct sockaddr *)&saddr, sizeof(saddr)) == SOCKET_ERROR) { debug( "connect() failed.\n"); }}} あとはssl-forward側から接続元アドレスを渡してやるように書き変えを行って動作を確認した。 = fusefs on FreeBSD = 新端末イメージにfusefsとsshfsをインストールした。 {{{ $ sudo portmaster sysutils/fusefs-sshfs }}} インストール後の指示に従って起動時にロードされるようにして: `/etc/rc.conf` {{{ fusefs_enable="YES" }}} ユーザ権限でマウントできるようにした: `/etc/sysctl.conf` {{{ vfs.usermount=1 }}}