added QSE_HTTPD_SERVER_TRANSPARENT to allow optional support for TPROXY.
changed to set the target to SECURE when the intercepted connection is known to be SECURE
This commit is contained in:
		| @ -527,9 +527,17 @@ static int get_server_root ( | ||||
| 			} | ||||
|  | ||||
| 			if (mth == QSE_HTTP_CONNECT)  | ||||
| 			{ | ||||
| 				root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_RAW; | ||||
| 			else if (loccfg->proxy.pseudonym[0])  | ||||
| 				root->u.proxy.pseudonym = loccfg->proxy.pseudonym; | ||||
| 			} | ||||
| 			else  | ||||
| 			{ | ||||
| 				if (loccfg->proxy.pseudonym[0])  | ||||
| 					root->u.proxy.pseudonym = loccfg->proxy.pseudonym; | ||||
|  | ||||
| 				if (server->dope.flags & QSE_HTTPD_SERVER_SECURE) | ||||
| 					root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_SECURE; | ||||
| 			} | ||||
|  | ||||
| 			goto proxy_ok; | ||||
| 		} | ||||
| @ -2047,6 +2055,7 @@ static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, int num, qse_xli_l | ||||
| 	if (pair && pair->val->type == QSE_XLI_STR &&  | ||||
| 	    qse_strxcmp (((qse_xli_str_t*)pair->val)->ptr, ((qse_xli_str_t*)pair->val)->len, QSE_T("yes")) == 0) dope.flags |= QSE_HTTPD_SERVER_SECURE;	 | ||||
|  | ||||
| 	dope.flags |= QSE_HTTPD_SERVER_TRANSPARENT; /* need this to support TPROXY when proxy.allow_intercept is enabled */ | ||||
| 	dope.detach = free_server_config; | ||||
| 	xserver = qse_httpd_attachserverstd (httpd, &dope, QSE_SIZEOF(server_xtn_t)); | ||||
| 	if (xserver == QSE_NULL)  | ||||
|  | ||||
| @ -211,6 +211,9 @@ struct qse_httpd_peer_t | ||||
|  | ||||
| 	/* == PRIVATE == */ | ||||
|  | ||||
| 	/* set by httpd to the client this peer has been created for */ | ||||
| 	qse_httpd_client_t* client;  | ||||
|  | ||||
| 	/* peer links for the proxy peer cache list in client. | ||||
| 	 * internal use only. don't mess with these */ | ||||
| 	qse_httpd_peer_t* next; | ||||
| @ -749,9 +752,10 @@ struct qse_httpd_client_t | ||||
|  | ||||
| enum qse_httpd_server_flag_t | ||||
| { | ||||
| 	QSE_HTTPD_SERVER_ACTIVE     = (1 << 0), | ||||
| 	QSE_HTTPD_SERVER_SECURE     = (1 << 1), | ||||
| 	QSE_HTTPD_SERVER_BINDTONWIF = (1 << 2) | ||||
| 	QSE_HTTPD_SERVER_ACTIVE      = (1 << 0), | ||||
| 	QSE_HTTPD_SERVER_SECURE      = (1 << 1), | ||||
| 	QSE_HTTPD_SERVER_BINDTONWIF  = (1 << 2), | ||||
| 	QSE_HTTPD_SERVER_TRANSPARENT = (1 << 3) | ||||
| }; | ||||
| typedef enum qse_httpd_server_flag_t qse_httpd_server_flag_t; | ||||
|  | ||||
|  | ||||
| @ -2270,8 +2270,7 @@ static void on_url_rewritten (qse_httpd_t* httpd, const qse_mchar_t* url, const | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int task_main_proxy ( | ||||
| 	qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| static int task_main_proxy (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) | ||||
| { | ||||
| 	task_proxy_t* proxy = (task_proxy_t*)task->ctx; | ||||
| 	proxy_peer_htrd_xtn_t* xtn; | ||||
| @ -2383,8 +2382,7 @@ static int task_main_proxy ( | ||||
| 	if (!(proxy->flags & PROXY_RAW)) | ||||
| 	{ | ||||
| 		/* set up a http reader to read a response from the peer */ | ||||
| 		proxy->peer_htrd = qse_htrd_open ( | ||||
| 			httpd->mmgr, QSE_SIZEOF(proxy_peer_htrd_xtn_t)); | ||||
| 		proxy->peer_htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(proxy_peer_htrd_xtn_t)); | ||||
| 		if (proxy->peer_htrd == QSE_NULL) goto oops; | ||||
| 		xtn = (proxy_peer_htrd_xtn_t*) qse_htrd_getxtn (proxy->peer_htrd); | ||||
| 		xtn->proxy = proxy; | ||||
| @ -2400,7 +2398,9 @@ static int task_main_proxy ( | ||||
| 	proxy->res_pending = 0; | ||||
|  | ||||
| 	/* get a cached peer connection */ | ||||
| 	peer_from_cache = qse_httpd_decacheproxypeer (httpd, client, &proxy->peer->nwad, &proxy->peer->local, (proxy->peer->flags & QSE_HTTPD_PEER_SECURE)); | ||||
| 	peer_from_cache = qse_httpd_decacheproxypeer ( | ||||
| 		httpd, client, &proxy->peer->nwad,  | ||||
| 		&proxy->peer->local, (proxy->peer->flags & QSE_HTTPD_PEER_SECURE)); | ||||
| 	if (peer_from_cache) | ||||
| 	{ | ||||
| 		qse_mchar_t tmpch; | ||||
| @ -2424,13 +2424,13 @@ static int task_main_proxy ( | ||||
| 		else | ||||
| 		{ | ||||
| 			/* the cached connection seems to be stale or invalid */ | ||||
| 	#if defined(QSE_HTTPD_DEBUG) | ||||
| 		#if defined(QSE_HTTPD_DEBUG) | ||||
| 			{ | ||||
| 				qse_mchar_t tmp[128]; | ||||
| 				qse_nwadtombs (&peer_from_cache->nwad, tmp, QSE_COUNTOF(tmp), QSE_NWADTOMBS_ALL); | ||||
| 				HTTPD_DBGOUT2 ("Decached and closed stale peer [%hs] - %zd\n", tmp, (qse_size_t)peer_from_cache->handle); | ||||
| 			} | ||||
| 	#endif | ||||
| 		#endif | ||||
| 			httpd->opt.scb.peer.close (httpd, peer_from_cache); | ||||
| 			qse_httpd_freemem (httpd, peer_from_cache); | ||||
|  | ||||
| @ -2445,6 +2445,8 @@ static int task_main_proxy ( | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		proxy->peer->client = client; | ||||
|  | ||||
| 		httpd->errnum = QSE_HTTPD_ENOERR; | ||||
| 		n = httpd->opt.scb.peer.open (httpd, proxy->peer); | ||||
| 		if (n <= -1) | ||||
| @ -2452,7 +2454,7 @@ static int task_main_proxy ( | ||||
| 			/* TODO: translate more error codes to http error codes... */ | ||||
| 			if (httpd->errnum == QSE_HTTPD_ENOENT) http_errnum = 404; | ||||
| 			else if (httpd->errnum == QSE_HTTPD_EACCES || | ||||
| 					 httpd->errnum == QSE_HTTPD_ECONN) http_errnum = 403; | ||||
| 			         httpd->errnum == QSE_HTTPD_ECONN) http_errnum = 403; | ||||
|  | ||||
| 		#if defined(QSE_HTTPD_DEBUG) | ||||
| 			{ | ||||
|  | ||||
| @ -964,66 +964,73 @@ static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server) | ||||
| 	{ | ||||
| 		/* TODO: logging. warning only */ | ||||
| 		/* this is not a hard failure */ | ||||
| 		HTTPD_DBGOUT1 ("Failed to enable SO_REUSERPORT on %zd\n", (qse_size_t)fd); | ||||
| 		HTTPD_DBGOUT1 ("Failed to set SO_REUSERPORT on %zd\n", (qse_size_t)fd); | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
|  | ||||
| /* TODO: linux. use capset() to set required capabilities just in case */ | ||||
| 	if (server->dope.flags & QSE_HTTPD_SERVER_TRANSPARENT) | ||||
| 	{ | ||||
| 	#if defined(IP_TRANSPARENT) | ||||
| 	/* remove the ip routing restriction that a packet can only | ||||
| 	 * be sent using a local ip address. this option is useful | ||||
| 	 * if transparency is achieved with TPROXY */ | ||||
| 		/* remove the ip routing restriction that a packet can only | ||||
| 		 * be sent using a local ip address. this option is useful | ||||
| 		 * if transparency is achieved with TPROXY */ | ||||
| 	 | ||||
| 		/* | ||||
| 		1) | ||||
| 		ip rule add fwmark 0x1/0x1 lookup 100 | ||||
| 		ip route add local 0.0.0.0/0 dev lo table 100 | ||||
| 	 | ||||
| 		2) | ||||
| 		iptables -t mangle -N DIVERT | ||||
| 		iptables -t mangle -A DIVERT -j MARK --set-mark 0x1/0x1 | ||||
| 		iptables -t mangle -A DIVERT -j ACCEPT | ||||
| 		iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j DIVERT | ||||
| 		iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
| 	 | ||||
| 		3) | ||||
| 		iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j MARK --set-mark 0x1/0x1 | ||||
| 		iptables -t mangle -A PREROUTING -p tcp -m mark 0x1/0x1 -j RETURN | ||||
| 		iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
| 	 | ||||
| 		4) | ||||
| 		iptables -t mangle -A PREROUTING -p tcp --sport 80 -j MARK --set-mark 0x1/0x1 | ||||
| 		iptables -t mangle -A PREROUTING -p tcp -m mark 0x1/0x1 -j RETURN | ||||
| 	        iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
| 	 | ||||
| 	 | ||||
| 		1) is required. | ||||
| 	        one of 2), 3), 4), and a variant is needed. | ||||
| 		Specifying -i and -o can narrow down the amount of packets when the upstream interface | ||||
| 		and the downstream interface are obvious. | ||||
|  | ||||
| 	/* | ||||
| 	1) | ||||
| 	ip rule add fwmark 0x1/0x1 lookup 100 | ||||
| 	ip route add local 0.0.0.0/0 dev lo table 100 | ||||
| 		If eth2 is an upstream and the eth1 is a downstream interface, | ||||
| 		iptables -t mangle -A PREROUTING -i eth2 -p tcp --sport 80 -j MARK --set-mark 0x1/0x1 | ||||
| 		iptables -t mangle -A PREROUTING -p tcp -m mark 0x1/0x1 -j RETURN | ||||
| 		iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
|  | ||||
| 	2) | ||||
| 	iptables -t mangle -N DIVERT | ||||
| 	iptables -t mangle -A DIVERT -j MARK --set-mark 0x1/0x1 | ||||
| 	iptables -t mangle -A DIVERT -j ACCEPT | ||||
| 	iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j DIVERT | ||||
| 	iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
| 		---------------------------------------------------------------------- | ||||
|  | ||||
| 	3) | ||||
| 	iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j MARK --set-mark 0x1/0x1 | ||||
| 	iptables -t mangle -A PREROUTING -p tcp -m mark 0x1/0x1 -j RETURN | ||||
| 	iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
| 		if the socket is bound to 99.99.99.99:8000, you may do... | ||||
| 		iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-ip 99.99.99.99 --on-port 8000 | ||||
|  | ||||
| 	4) | ||||
| 	iptables -t mangle -A PREROUTING -p tcp --sport 80 -j MARK --set-mark 0x1/0x1 | ||||
| 	iptables -t mangle -A PREROUTING -p tcp -m mark 0x1/0x1 -j RETURN | ||||
|         iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
| 		iptables -t mangle -A PREROUTING -p tcp  ! -s 127.0.0.0/255.0.0.0 --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-ip 0.0.0.0 --on-port 8000 | ||||
|  | ||||
|  | ||||
| 	1) is required. | ||||
|         one of 2), 3), 4), and a variant is needed. | ||||
| 	Specifying -i and -o can narrow down the amount of packets when the upstream interface | ||||
| 	and the downstream interface are obvious. | ||||
|  | ||||
| 	If eth2 is an upstream and the eth1 is a downstream interface, | ||||
| 	iptables -t mangle -A PREROUTING -i eth2 -p tcp --sport 80 -j MARK --set-mark 0x1/0x1 | ||||
| 	iptables -t mangle -A PREROUTING -p tcp -m mark 0x1/0x1 -j RETURN | ||||
|         iptables -t mangle -A PREROUTING -i eth1 -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8000 | ||||
|  | ||||
| 	---------------------------------------------------------------------- | ||||
|  | ||||
| 	if the socket is bound to 99.99.99.99:8000, you may do... | ||||
| 	iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-ip 99.99.99.99 --on-port 8000 | ||||
|  | ||||
| 	iptables -t mangle -A PREROUTING -p tcp  ! -s 127.0.0.0/255.0.0.0 --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-ip 0.0.0.0 --on-port 8000 | ||||
|  | ||||
| 	IP_TRANSPRENT is needed for: | ||||
| 	- accepting TPROXYed connections | ||||
| 	- binding to a non-local IP address (IP address the local system doesn't have) | ||||
| 	- using a non-local IP address as a source | ||||
| 	-  | ||||
| 	 */ | ||||
| 	flag = 1; | ||||
| 	setsockopt (fd, SOL_IP, IP_TRANSPARENT, &flag, QSE_SIZEOF(flag)); | ||||
| 		IP_TRANSPRENT is needed for: | ||||
| 			- accepting TPROXYed connections | ||||
| 			- binding to a non-local IP address (IP address the local system doesn't have) | ||||
| 			- using a non-local IP address as a source | ||||
| 		 */ | ||||
| 		flag = 1; | ||||
| 		if (setsockopt (fd, SOL_IP, IP_TRANSPARENT, &flag, QSE_SIZEOF(flag)) <= -1) | ||||
| 		{ | ||||
| 			/* TODO: logging. warning only */ | ||||
| 			/* this is not a hard failure */ | ||||
| 			HTTPD_DBGOUT1 ("Failed to set IP_TRANSPARENT on %zd\n", (qse_size_t)fd); | ||||
| 		} | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	if (server->dope.flags & QSE_HTTPD_SERVER_BINDTONWIF) | ||||
| 	{ | ||||
| @ -1032,11 +1039,10 @@ static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server) | ||||
| 		qse_size_t len; | ||||
|  | ||||
| 		len = qse_nwifindextombs (server->dope.nwif, tmp, QSE_COUNTOF(tmp)); | ||||
|  | ||||
| 		if (len <= 0 || setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE, tmp, len) <= -1) | ||||
| 		{ | ||||
| 			/* TODO: logging ... */ | ||||
| 			qse_httpd_seterrnum (httpd, ((len <= 0)? QSE_HTTPD_EINVAL: SKERR_TO_ERRNUM())); | ||||
| 			HTTPD_DBGOUT2 ("Failed to set SO_BINDTODEVICE to %hs on %zd\n", tmp, (qse_size_t)fd); | ||||
| 			goto oops; | ||||
| 		} | ||||
| 	#endif | ||||
| @ -1294,7 +1300,6 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client) | ||||
|  | ||||
| 		server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, client->server); | ||||
|  | ||||
| 		 | ||||
| 		if (!server_xtn->ssl_ctx) | ||||
| 		{ | ||||
| 			/* performed the delayed ssl initialization */ | ||||
| @ -1422,11 +1427,18 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer) | ||||
| 		goto oops; | ||||
| 	} | ||||
|  | ||||
| /* TODO: set transparent and bind only if the server is transparent */ | ||||
| 	if (peer->client && peer->client->server &&  | ||||
| 	    (peer->client->server->dope.flags & QSE_HTTPD_SERVER_TRANSPARENT)) | ||||
| 	{ | ||||
| 	#if defined(IP_TRANSPARENT) | ||||
| 	flag = 1; | ||||
| 	setsockopt (fd, SOL_IP, IP_TRANSPARENT, &flag, QSE_SIZEOF(flag)); | ||||
| 		flag = 1; | ||||
| 		if (setsockopt (fd, SOL_IP, IP_TRANSPARENT, &flag, QSE_SIZEOF(flag)) <= -1) | ||||
| 		{ | ||||
| 			/* this is not a hard failure */ | ||||
| 			HTTPD_DBGOUT1 ("Failed to set IP_TRANSPARENT on peer socket %zd\n", (qse_size_t)fd); | ||||
| 		} | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| 	/* don't use invalid binding address */ | ||||
| 	if (bindaddrsize >= 0 && | ||||
| @ -3457,7 +3469,7 @@ static int query_server ( | ||||
| 	{ | ||||
| 		case QSE_HTTPD_SERVERSTD_SSL: | ||||
| 			/* you must specify the certificate and the key file to be able | ||||
| 			 * to use SSL */ | ||||
| 			 * to use SSL. not supported by this sample implmentation. */ | ||||
| 			qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOENT); | ||||
| 			return -1; | ||||
|  | ||||
|  | ||||
| @ -822,7 +822,9 @@ static int accept_client ( | ||||
|  | ||||
| /* TODO: check maximum number of client. if exceed call client.close */ | ||||
|  | ||||
| 		if (server->dope.flags & QSE_HTTPD_SERVER_SECURE) clibuf.status |= QSE_HTTPD_CLIENT_SECURE; | ||||
| 		if (server->dope.flags & QSE_HTTPD_SERVER_SECURE)  | ||||
| 			clibuf.status |= QSE_HTTPD_CLIENT_SECURE; | ||||
|  | ||||
| 		clibuf.server = server; | ||||
|  | ||||
| #if 0 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user