• Java 等后端应用如何获取客户端真实IP —— 筑梦之路


    需求说明

    现有一套Java开发的应用,需要能获取到用户访问的真实IP地址,以此来过滤到一些不安全的因素。而实际部署的场景中Java服务提供给用户访问需要经过多次代理,默认情况下是无法获取到客户端真实IP地址的,因此要实现该需求,就得将客户端真实IP地址透传到后端。

    访问路径

    如何实现

    haproxy上配置

    1. # haproxy.cfg
    2. defaults
    3. mode http
    4. log global
    5. option httplog
    6. option dontlognull
    7. option http-server-close
    8. log 127.0.0.1 local3
    9. option forwardfor except 127.0.0.0/8
    10. option redispatch
    11. retries 3
    12. timeout http-request 10s
    13. timeout queue 1m
    14. timeout connect 10s
    15. timeout client 5m
    16. timeout server 5m
    17. timeout http-keep-alive 10s
    18. timeout check 10s
    19. unique-id-format %{+X}o\ %ci%cp%fi%fp%Ts%rt%pid
    20. frontend https_link_ha
    21. bind *:443 ssl crt /usr/local/etc/haproxy/cert/crt/ ca-file /usr/local/etc/haproxy/cert/ca/ca.pem verify optional
    22. #log 127.0.0.1 local3
    23. mode http
    24. log-format "%ID %ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
    25. option accept-invalid-http-request
    26. # 配置请求头
    27. http-request set-header x-request-id %[unique-id]
    28. http-request set-header x-request-time %[date()]
    29. http-request set-header X-Real-IP %[src]
    30. default_backend pre
    31. backend pre
    32. server 1 192.168.100.100:8080 check inter 1500 rise 3 fall 3 weight 3
    33. server 2 192.168.100.101:9000 check inter 1500 rise 3 fall 3 weight 4
    34. server 3 192.168.100.102:8090 check inter 1500 rise 3 fall 3 weight 5

    其中主要是两个配置:

    • option forwardfor       except 127.0.0.0/8在由Haproxy发往后端的请求中加上XFF首部,其值是前个客户端的IP。

    • http-request set-header X-Real-IP %[src]X-Real-IP中设置客户端IP。

    nginx上配置

    1. # nginx.conf 日志格式
    2. log_format main '$remote_addr - $remote_user [$time_local] "$request" "$http_x_forwarded_for" ';
    3. # location 反向代理的配置
    4. proxy_set_header Host $host;
    5. proxy_set_header X-Real-IP $remote_addr;
    6. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    更多参考资料:https://www.cnblogs.com/yanzi2020/p/17471481.html

    ingress上配置

    默认情况下,Ingress没有开启XFF。

    Ingress上要使用XFF,需要使用到以下三个参数:

    • use-forwarded-headers:是否开启XFF头传递,默认是false

    • forwarded-for-headerXFF的真实header名,默认是X-Forwarded-For

    • compute-full-forwarded-for:列出客户端访问所经过的代理IP,默认情况下,XFF是从remote_addr中获取的值。

    1. # 在Nginx Ingress的ConfigMap里增加以下两个配置
    2. use-forwarded-headers: 'true'
    3. compute-full-forwarded-for: 'true'

     注意:不是所有的场景都能通过XFF获取到用户的真实IP,比如当SLB前面还有CDN的情况下,获取的可能就是CDN的来源IP

    traefik上配置

     官方文档:Traefik EntryPoints Documentation - Traefik

    命令行方式

    --entryPoints.web.address=:80
    --entryPoints.web.forwardedHeaders.insecure

    1. # k8s yaml文件示例,仅做参考
    2. ---
    3. apiVersion: apps/v1
    4. kind: Deployment
    5. metadata:
    6. annotations:
    7. meta.helm.sh/release-name: traefik
    8. meta.helm.sh/release-namespace: default
    9. labels:
    10. app.kubernetes.io/instance: traefik
    11. app.kubernetes.io/managed-by: Helm
    12. app.kubernetes.io/name: traefik
    13. helm.sh/chart: traefik-9.11.0
    14. name: traefik
    15. namespace: default
    16. resourceVersion: '505763774'
    17. spec:
    18. progressDeadlineSeconds: 600
    19. replicas: 6
    20. revisionHistoryLimit: 10
    21. selector:
    22. matchLabels:
    23. app.kubernetes.io/instance: traefik
    24. app.kubernetes.io/name: traefik
    25. strategy:
    26. rollingUpdate:
    27. maxSurge: 1
    28. maxUnavailable: 1
    29. type: RollingUpdate
    30. template:
    31. metadata:
    32. creationTimestamp: null
    33. labels:
    34. app.kubernetes.io/instance: traefik
    35. app.kubernetes.io/managed-by: Helm
    36. app.kubernetes.io/name: traefik
    37. helm.sh/chart: traefik-9.11.0
    38. spec:
    39. containers:
    40. - args:
    41. - '--global.checknewversion'
    42. - '--global.sendanonymoususage'
    43. - '--entryPoints.traefik.address=:9000/tcp'
    44. - '--entryPoints.web.address=:8000/tcp'
    45. - '--entryPoints.websecure.address=:8443/tcp'
    46. - '--api.dashboard=true'
    47. - '--ping=true'
    48. - '--providers.kubernetescrd'
    49. - '--providers.kubernetesingress'
    50. - '--entrypoints.web.forwardedHeaders.insecure'
    51. - '--entrypoints.websecure.forwardedHeaders.insecure'
    52. image: 'traefik:2.3.3'
    53. imagePullPolicy: IfNotPresent
    54. livenessProbe:
    55. failureThreshold: 3
    56. httpGet:
    57. path: /ping
    58. port: 9000
    59. scheme: HTTP
    60. initialDelaySeconds: 10
    61. periodSeconds: 10
    62. successThreshold: 1
    63. timeoutSeconds: 2
    64. name: traefik
    65. ports:
    66. - containerPort: 9000
    67. name: traefik
    68. protocol: TCP
    69. - containerPort: 8000
    70. name: web
    71. protocol: TCP
    72. - containerPort: 8443
    73. name: websecure
    74. protocol: TCP
    75. readinessProbe:
    76. failureThreshold: 1
    77. httpGet:
    78. path: /ping
    79. port: 9000
    80. scheme: HTTP
    81. initialDelaySeconds: 10
    82. periodSeconds: 10
    83. successThreshold: 1
    84. timeoutSeconds: 2
    85. resources: {}
    86. securityContext:
    87. capabilities:
    88. drop:
    89. - ALL
    90. readOnlyRootFilesystem: true
    91. runAsGroup: 65532
    92. runAsNonRoot: true
    93. runAsUser: 65532
    94. terminationMessagePath: /dev/termination-log
    95. terminationMessagePolicy: File
    96. volumeMounts:
    97. - mountPath: /data
    98. name: data
    99. - mountPath: /tmp
    100. name: tmp
    101. dnsPolicy: ClusterFirst
    102. restartPolicy: Always
    103. schedulerName: default-scheduler
    104. securityContext:
    105. fsGroup: 65532
    106. serviceAccount: traefik
    107. serviceAccountName: traefik
    108. terminationGracePeriodSeconds: 60
    109. volumes:
    110. - emptyDir: {}
    111. name: data
    112. - emptyDir: {}
    113. name: tmp
    114. status:
    115. availableReplicas: 6
    116. conditions:
    117. - lastTransitionTime: '2022-10-10T07:58:50Z'
    118. lastUpdateTime: '2022-10-10T07:58:50Z'
    119. message: Deployment has minimum availability.
    120. reason: MinimumReplicasAvailable
    121. status: 'True'
    122. type: Available
    123. - lastTransitionTime: '2020-11-25T22:53:59Z'
    124. lastUpdateTime: '2022-11-17T10:44:40Z'
    125. message: ReplicaSet "traefik-54bf67c74d" has successfully progressed.
    126. reason: NewReplicaSetAvailable
    127. status: 'True'
    128. type: Progressing
    129. observedGeneration: 13
    130. readyReplicas: 6
    131. replicas: 6
    132. updatedReplicas: 6
    133. ---
    134. apiVersion: v1
    135. kind: Service
    136. metadata:
    137. annotations:
    138. meta.helm.sh/release-name: traefik
    139. meta.helm.sh/release-namespace: default
    140. labels:
    141. app.kubernetes.io/instance: traefik
    142. app.kubernetes.io/managed-by: Helm
    143. app.kubernetes.io/name: traefik
    144. helm.sh/chart: traefik-9.11.0
    145. name: traefik
    146. namespace: default
    147. resourceVersion: '505762379'
    148. spec:
    149. clusterIP: 10.96.252.109
    150. externalTrafficPolicy: Cluster
    151. ports:
    152. - name: web
    153. nodePort: 30079
    154. port: 80
    155. protocol: TCP
    156. targetPort: web
    157. selector:
    158. app.kubernetes.io/instance: traefik
    159. app.kubernetes.io/name: traefik
    160. sessionAffinity: None
    161. type: NodePort
    162. status:
    163. loadBalancer: {}

    在deployment部署中的traefik启动参数中添加

     - '--entrypoints.web.forwardedHeaders.insecure'

    - '--entrypoints.websecure.forwardedHeaders.insecure'

    启动参数

    本文仅做记录和参考,在实际使用中需要充分测试。

  • 相关阅读:
    java计算机毕业设计动漫论坛系统MyBatis+系统+LW文档+源码+调试部署
    雅思口语高分课程
    Spring事务的嵌套的详细理解,以及事务失效的场景解惑
    【神印王座】伊莱克斯正式登场,皓晨通过永恒试炼,喜提两外挂,采儿丧失四感
    手把手教你配置vscode+wsl开发环境
    总结springboot项目中一些后端接收前端传参的方法
    【C语言】【动态内存管理】malloc,free,calloc,realloc
    很后悔,才发现这个API管理神器
    设计模式(上)
    C#:实现判断整数是否是2的N次方算法(附完整源码)
  • 原文地址:https://blog.csdn.net/qq_34777982/article/details/134421655