diff --git a/src/obproxy/obutils/ob_proxy_config.h b/src/obproxy/obutils/ob_proxy_config.h index ded12f80..e01eb05d 100644 --- a/src/obproxy/obutils/ob_proxy_config.h +++ b/src/obproxy/obutils/ob_proxy_config.h @@ -213,6 +213,7 @@ class ObProxyConfig : public common::ObCommonConfig DEF_BOOL(enable_cluster_checkout, "true", "if enable cluster checkout, proxy will send cluster name when login and server will check it", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER, CFG_MULTI_LEVEL_GLOBAL); DEF_BOOL(enable_proxy_scramble, "false", "if enable proxy scramble, proxy will send client its variable scramble num, not support old observer", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_SYS, CFG_MULTI_LEVEL_GLOBAL); DEF_BOOL(enable_client_ip_checkout, "true", "if enabled, proxy send client ip when login", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER, CFG_MULTI_LEVEL_GLOBAL); + DEF_BOOL(enable_client_ip_attr_trust, "true", "if enabled, proxy trusts the __client_ip connect attribute reported by the client itself and forwards it to observer; if disabled, proxy forwards the peer address it detected, and only accepts __client_ip from an upstream obproxy (__mysql_client_type=__ob_proxy). Only effective when enable_client_ip_checkout is true", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER, CFG_MULTI_LEVEL_GLOBAL); //connection related DEF_INT(connect_observer_max_retries, "3", "[2,5]", "max retries to do connect", CFG_NO_NEED_REBOOT, CFG_SECTION_OBPROXY, CFG_VISIBLE_LEVEL_USER, CFG_MULTI_LEVEL_GLOBAL); diff --git a/src/obproxy/proxy/mysql/ob_mysql_transact.cpp b/src/obproxy/proxy/mysql/ob_mysql_transact.cpp index 92ec1226..15d91ad3 100644 --- a/src/obproxy/proxy/mysql/ob_mysql_transact.cpp +++ b/src/obproxy/proxy/mysql/ob_mysql_transact.cpp @@ -5241,6 +5241,7 @@ inline int ObMysqlTransact::handle_oceanbase_handshake_pkt(ObTransState &s, uint param.use_ob_protocol_v2_compress_ = (s.sm_->compression_algorithm_.level_ != 0 && use_ob_protocol_v2); param.use_ssl_ = use_ssl; param.enable_client_ip_checkout_ = enable_client_ip_checkout; + param.enable_client_ip_attr_trust_ = s.mysql_config_params_->enable_client_ip_attr_trust_; param.cs_id_version_ = client_session->get_cs_id_version(); param.enable_full_link_trace_ = s.sm_->enable_full_link_trace_; if (is_binlog_request(s) && OB_NOT_NULL(s.sm_->multi_level_config_)) { diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp index b45eede0..6fbeb024 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.cpp @@ -82,6 +82,7 @@ ObMysqlConfigParams::ObMysqlConfigParams() enable_bad_route_reject_(false), enable_cluster_checkout_(true), enable_client_ip_checkout_(true), + enable_client_ip_attr_trust_(true), enable_proxy_scramble_(false), enable_compression_protocol_(false), enable_ob_protocol_v2_(false), @@ -189,6 +190,7 @@ int ObMysqlConfigParams::assign_config(const ObProxyConfig &proxy_config) CONFIG_ITEM_ASSIGN(enable_bad_route_reject); CONFIG_ITEM_ASSIGN(enable_cluster_checkout); CONFIG_ITEM_ASSIGN(enable_client_ip_checkout); + CONFIG_ITEM_ASSIGN(enable_client_ip_attr_trust); CONFIG_ITEM_ASSIGN(enable_proxy_scramble); CONFIG_ITEM_ASSIGN(enable_compression_protocol); CONFIG_ITEM_ASSIGN(enable_ob_protocol_v2); @@ -347,7 +349,7 @@ DEF_TO_STRING(ObMysqlConfigParams) K_(proxy_service_mode), K_(server_routing_mode), K_(proxy_id), K_(proxy_idc_name), K_(client_max_memory_size), K_(enable_cpu_isolate), K_(default_inactivity_timeout), K_(enable_partition_table_route), K_(enable_pl_route), - K_(enable_cluster_checkout), K_(enable_client_ip_checkout), K_(enable_proxy_scramble), + K_(enable_cluster_checkout), K_(enable_client_ip_checkout), K_(enable_client_ip_attr_trust), K_(enable_proxy_scramble), K_(enable_compression_protocol), K_(enable_ob_protocol_v2), K_(enable_reroute), K_(enable_weak_reroute), K_(enable_index_route), K_(enable_causal_order_read), K_(ip_listen_mode)); diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h index 802ab58f..c2af13e1 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_config_processor.h @@ -109,6 +109,7 @@ struct ObMysqlConfigParams : public ObConfigInfo CfgBool enable_bad_route_reject_; CfgBool enable_cluster_checkout_; CfgBool enable_client_ip_checkout_; + CfgBool enable_client_ip_attr_trust_; CfgBool enable_proxy_scramble_; CfgBool enable_compression_protocol_; CfgBool enable_ob_protocol_v2_; diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp index 9e23b3c1..0a482fde 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp +++ b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.cpp @@ -34,7 +34,7 @@ int64_t ObHandshakeResponseParam::to_string(char *buf, const int64_t buf_len) co J_OBJ_START(); J_KV(K_(is_saved_login), K_(cluster_name), K_(proxy_scramble), K_(conn_id_buf), K_(proxy_conn_id_buf), K_(global_vars_version_buf), - K_(cap_buf), K_(proxy_version_buf), K_(client_ip_buf), + K_(cap_buf), K_(proxy_version_buf), K_(client_ip_buf), K_(enable_client_ip_attr_trust), K_(proxy_idc_name), K_(proxy_service_name), K_(proxy_failover_mode)); J_OBJ_END(); return pos; @@ -268,8 +268,32 @@ int ObMysqlPacketRewriter::rewrite_handshake_response_packet( tg_hsr.set_database(ObString::make_empty_string()); } - // find client_ip + // Decide whether the __client_ip connect attribute reported by the client can be trusted. + // param.client_ip_buf_ already holds the peer address detected by proxy (write_client_addr_buf). + // The self-reported value is only needed when the peer address is not the real client, i.e. + // when the client is an upstream obproxy (__mysql_client_type=__ob_proxy) or the deployment + // sits behind a NAT load balancer. Drivers such as OceanBase Connector/J report their local + // socket address in __client_ip; inside a container that is the container address, which then + // fails ob_tcp_invited_nodes / user host checks on observer. With enable_client_ip_attr_trust + // disabled, only an upstream obproxy may override the detected address. + bool trust_client_ip_attr = false; if (RUN_MODE_PROXY == g_run_mode && param.enable_client_ip_checkout_) { + if (param.enable_client_ip_attr_trust_) { + trust_client_ip_attr = true; + } else { + ObStringKV string_kv; + for (int64_t i = 0; OB_SUCC(ret) && !trust_client_ip_attr && i < tg_hsr.get_connect_attrs().count(); ++i) { + string_kv = tg_hsr.get_connect_attrs().at(i); + if (0 == string_kv.key_.case_compare(OB_MYSQL_CLIENT_MODE) + && 0 == string_kv.value_.compare(OB_MYSQL_CLIENT_OBPROXY_MODE)) { + trust_client_ip_attr = true; + } + } + } + } + + // find client_ip + if (trust_client_ip_attr) { ObStringKV string_kv; for (int64_t i = 0; OB_SUCC(ret) && i < tg_hsr.get_connect_attrs().count(); ++i) { string_kv = tg_hsr.get_connect_attrs().at(i); @@ -296,11 +320,15 @@ int ObMysqlPacketRewriter::rewrite_handshake_response_packet( if (OB_FAIL(tg_hsr.get_connect_attrs().push_back(kv))) { LOG_WDIAG("fail push back transparent transmit connect attrs", K(kv), K(ret)); } else { /* succ */ } - } else if (!find_client_ip - && param.enable_client_ip_checkout_ + } else if (!find_client_ip && 0 == kv.key_.case_compare(OB_MYSQL_CLIENT_IP) - && !kv.value_.empty()){ - snprintf(param.client_ip_buf_, MAX_IP_ADDR_LENGTH, "%.*s", kv.value_.length(), kv.value_.ptr()); + && !kv.value_.empty()) { + if (trust_client_ip_attr) { + snprintf(param.client_ip_buf_, MAX_IP_ADDR_LENGTH, "%.*s", kv.value_.length(), kv.value_.ptr()); + } else { + LOG_DEBUG("ignore client reported __client_ip, use detected peer address instead", + "reported_client_ip", kv.value_, "detected_client_ip", param.client_ip_buf_); + } find_client_ip = true; } else { /* do nothing */ } } diff --git a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h index 423e2696..9e3f3a51 100644 --- a/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h +++ b/src/obproxy/proxy/mysqllib/ob_mysql_packet_rewriter.h @@ -75,6 +75,7 @@ struct ObHandshakeResponseParam int64_t cluster_id_; bool use_ssl_; bool enable_client_ip_checkout_; + bool enable_client_ip_attr_trust_; bool enable_full_link_trace_; ObClientSessionIDVersion cs_id_version_; common::ObString cluster_name_;