├── .github └── workflows │ ├── go-releaser.yml │ └── go.yml ├── .gitignore ├── LICENSE ├── README.md ├── cloudprefixes.go ├── go.mod ├── go.sum └── pkg ├── db ├── main.go └── main_test.go └── update ├── aws.go ├── aws_test.go ├── azure.go ├── azure_test.go ├── export_tests.go ├── geofeed.go ├── geofeed_test.go ├── github.go ├── github_test.go ├── google.go ├── google_test.go ├── main.go ├── main_test.go ├── oracle.go ├── oracle_test.go └── testdata ├── aws_response.json ├── azure_response.html ├── azure_response.json ├── cloudflare_response.txt ├── digitalocean_response.csv ├── github_response.json ├── google_response.json └── oracle_response.json /.github/workflows/go-releaser.yml: -------------------------------------------------------------------------------- 1 | name: goreleaser 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | goreleaser: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - 16 | name: Checkout 17 | uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 20 | - 21 | name: Set up Go 22 | uses: actions/setup-go@v5 23 | - 24 | name: Run GoReleaser 25 | uses: goreleaser/goreleaser-action@v6 26 | with: 27 | distribution: goreleaser 28 | version: '~> v2' 29 | args: release --clean 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | on: [push] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | 8 | steps: 9 | - uses: actions/checkout@v4 10 | - name: Setup Go 11 | uses: actions/setup-go@v5 12 | with: 13 | go-version: '1.22.x' 14 | - name: Install dependencies 15 | run: go get . 16 | - name: Build 17 | run: go build -v ./... 18 | - name: Test with the Go CLI 19 | run: go test 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | 24 | # project files and artifacts 25 | cloudprefixes 26 | data/ 27 | cloudprefixes.db 28 | 29 | .vscode/ 30 | 31 | dist/ 32 | *.bak 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | cloudprefixes is a lightweight tool designed to assist in recon by handling IP prefixes published by cloud and hosting providers. The tool automatically retrieves these prefixes, stores them in an SQLite database, and offers a straightforward interface for querying the database, either through the command line or by integrating with other security tools. 2 | 3 | Key Features: 4 | - Service Association: Associate a managed service to an IP address assist in focus of further recon. 5 | - Prefix Management: Fetch and update IP prefixes from various cloud platforms (e.g., AWS, GitHub) with a single command, ensuring your database stays up to date. 6 | - Query Functionality: Search for cloud provider information associated with one or multiple IP addresses, either as command-line arguments or via standard input. 7 | - Extensibility: The SQLite database allows easy integration with third-party tools and scripts, making it flexible for security automation and further recon use cases. 8 | - Prettify Output: Easily pipe the output into tools like jq for clean, human-readable JSON formatting. 9 | 10 | 11 | # Useage 12 | 13 | ``` 14 | $ cloudprefixes -h 15 | 16 | __ _ ___ __ __ ___ ____ ____ ___ _____ ____ __ __ 17 | / | T / \| T | \ | \| \ / _| l | T T 18 | / /| | Y | | | \| o | D )/ [_| __j| T| | | 19 | / / | l___| O | | | D | _/| /Y _| l_ | |l_ _j 20 | / \_| | | : | | | | \| [_| _] | || | 21 | \ | l l | | | | . | | T j l| | | 22 | \____l_____j\___/ \__,_l_____l__j l__j\_l_____l__j |____|__j__| 23 | 24 | Usage 25 | cloudprefixes [OPTION]... [IP ADDRESS]... 26 | Search cloud prefixes in database for each IP ADDRESS 27 | 28 | With no IP ADDRESS, read standard input. 29 | 30 | Options: 31 | -dbpath string 32 | path to database file (default "./cloudprefixes.db") 33 | -update 34 | update all prefixes in database and exit 35 | 36 | ``` 37 | 38 | Before being able to query the database, it needs to be populated with the ranges by executing the following 39 | ``` 40 | $ cloudprefixes -update 41 | ``` 42 | 43 | Querying can be multiple IP addresses as arguments or piped to stdin 44 | ``` 45 | $ ./cloudprefixes 192.30.252.1 2600:1f13:0a0d:a700::1 46 | [{"prefix":"192.30.252.0/22","platform":"GitHub","service":"Hooks"},{"prefix":"192.30.252.0/22","platform":"GitHub","service":"Web"},{"prefix":"192.30.252.0/22","platform":"GitHub","service":"API"},{"prefix":"192.30.252.0/22","platform":"GitHub","service":"Git"},{"prefix":"192.30.252.0/22","platform":"GitHub","service":"GithubEnterpriseImporter"},{"prefix":"192.30.252.0/22","platform":"GitHub","service":"Copilot"}] 47 | [{"prefix":"2600:1f13::/36","platform":"AWS","region":"us-west-2","service":"AMAZON","metadata":"{\"network_boarder_group\":\"us-west-2\"}"},{"prefix":"2600:1f13::/36","platform":"AWS","region":"us-west-2","service":"EC2","metadata":"{\"network_boarder_group\":\"us-west-2\"}"},{"prefix":"2600:1f13:a0d:a700::/56","platform":"AWS","region":"us-west-2","service":"EC2_INSTANCE_CONNECT","metadata":"{\"network_boarder_group\":\"us-west-2\"}"}] 48 | ``` 49 | 50 | Piping the output to jq will prettify it 51 | ``` 52 | $ ./cloudprefixes 2600:1f13:0a0d:a700::1 |jq 53 | [ 54 | { 55 | "prefix": "2600:1f13::/36", 56 | "platform": "AWS", 57 | "region": "us-west-2", 58 | "service": "AMAZON", 59 | "metadata": "{\"network_boarder_group\":\"us-west-2\"}" 60 | }, 61 | { 62 | "prefix": "2600:1f13::/36", 63 | "platform": "AWS", 64 | "region": "us-west-2", 65 | "service": "EC2", 66 | "metadata": "{\"network_boarder_group\":\"us-west-2\"}" 67 | }, 68 | { 69 | "prefix": "2600:1f13:a0d:a700::/56", 70 | "platform": "AWS", 71 | "region": "us-west-2", 72 | "service": "EC2_INSTANCE_CONNECT", 73 | "metadata": "{\"network_boarder_group\":\"us-west-2\"}" 74 | } 75 | ] 76 | ``` 77 | 78 | The database is SQLite so can be queried directly 79 | ``` 80 | $ sqlite3 cloudprefixes.db 81 | SQLite version 3.45.1 2024-01-30 16:01:20 82 | Enter ".help" for usage hints. 83 | sqlite> select service, count(prefix) from cloud_prefixes where platform is "GitHub" and ip_version = 6 group by service; 84 | API|2 85 | Actions|862 86 | Copilot|2 87 | Git|2 88 | GithubEnterpriseImporter|2 89 | Hooks|2 90 | Pages|4 91 | Web|2 92 | ``` 93 | 94 | 95 | # Prefixes 96 | ## Major Cloud 97 | 98 | The major cloud providers publish the most useful information about their prefixes. They include what service the prefixes are associated with. Each provider has their own format requiring a custom parser for each one. 99 | 100 | ### Oracle 101 | - https://docs.oracle.com/en-us/iaas/tools/public_ip_ranges.json 102 | 103 | Tag details from https://docs.oracle.com/en-us/iaas/Content/General/Concepts/addressranges.htm 104 | 105 | Valid tag values: 106 | - `OCI`: The VCN CIDR blocks 107 | - `OSN`: The CIDR block ranges for the Oracle Services Network. 108 | - `OBJECT_STORAGE`: The CIDR block ranges used by the Object Storage service. For more information, see Overview of Object Storage. 109 | 110 | ### Google 111 | - GCP - https://www.gstatic.com/ipranges/cloud.json 112 | - Google APIs - https://www.gstatic.com/ipranges/goog.json 113 | 114 | ### AWS 115 | - https://ip-ranges.amazonaws.com/ip-ranges.json 116 | 117 | ### Azure 118 | - Public - https://www.microsoft.com/en-us/download/details.aspx?id=56519 119 | - US Government - https://www.microsoft.com/en-us/download/details.aspx?id=57063 120 | - China - https://www.microsoft.com/en-us/download/details.aspx?id=57062 121 | - Germany - https://www.microsoft.com/en-au/download/details.aspx?id=57064 122 | 123 | Service tag details: https://learn.microsoft.com/en-us/azure/virtual-network/service-tags-overview 124 | 125 | ### GitHub 126 | - https://api.github.com/meta 127 | 128 | https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses 129 | 130 | 131 | ## Geofeed 132 | 133 | Geofeed is a list of self-published IP address ranges with geolocation information. The standard for geofeed is published under [RFC8805](https://datatracker.ietf.org/doc/html/rfc8805) and contains the following fields: 134 | - IP Prefix (required) 135 | - Alpha2code 136 | - Region 137 | - City 138 | - Postcode 139 | 140 | For example: 141 | ``` 142 | # Constant.com / Vultr.com GeoFeed (AS20473) 143 | # Email: support@vultr.com 144 | # Last Updated: 2024-09-29 13:38:43 145 | 8.3.29.0/24,US,US-CA,Los Angeles,90012 146 | 8.6.8.0/24,US,US-CA,Los Angeles,90012 147 | 8.6.193.0/24,US,US-FL,Miami,33142 148 | 8.9.3.0/24,US,US-NJ,Piscataway,08854 149 | 8.9.4.0/24,US,US-NJ,Piscataway,08854 150 | 8.9.5.0/24,US,US-NJ,Piscataway,08854 151 | ``` 152 | 153 | CloudFlare is an example of a provider who publishes a list with only prefixes. It is unclear if they intended to publish to RFC8805 but this can still be process with CSV parser used for geofeeds. 154 | 155 | There many geofeeds published and more can easily be added. For now the sources are a few minor cloud providers 156 | 157 | ## Digital Ocean 158 | - https://digitalocean.com/geo/google.csv 159 | 160 | ## Linode 161 | - https://geoip.linode.com/ 162 | 163 | ## Vultr 164 | - https://geofeed.constant.com/ 165 | 166 | ## CloudFlare 167 | - https://www.cloudflare.com/ips-v4 168 | - https://www.cloudflare.com/ips-v6 169 | 170 | # License 171 | 172 | This project is licensed under the GPLv3 License - see the LICENSE file for details -------------------------------------------------------------------------------- /cloudprefixes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "encoding/json" 6 | "flag" 7 | "fmt" 8 | "log" 9 | "os" 10 | "path/filepath" 11 | 12 | "github.com/mchaffe/cloudprefixes/pkg/db" 13 | "github.com/mchaffe/cloudprefixes/pkg/update" 14 | ) 15 | 16 | type Results struct { 17 | IP string `json:"ip"` 18 | Info []db.PrefixInfo `json:"info"` 19 | } 20 | 21 | func main() { 22 | 23 | flag.Usage = func() { 24 | fmt.Println(` 25 | __ _ ___ __ __ ___ ____ ____ ___ _____ ____ __ __ 26 | / | T / \| T | \ | \| \ / _| l | T T 27 | / /| | Y | | | \| o | D )/ [_| __j| T| | | 28 | / / | l___| O | | | D | _/| /Y _| l_ | |l_ _j 29 | / \_| | | : | | | | \| [_| _] | || | 30 | \ | l l | | | | . | | T j l| | | 31 | \____l_____j\___/ \__,_l_____l__j l__j\_l_____l__j |____|__j__|`) 32 | fmt.Printf("\nUsage\n %s [OPTION]... [IP ADDRESS]...\n", filepath.Base(os.Args[0])) 33 | fmt.Println("Search cloud prefixes in database for each IP ADDRESS") 34 | fmt.Println("\nWith no IP ADDRESS, read standard input.") 35 | fmt.Println("\nOptions:") 36 | flag.PrintDefaults() 37 | } 38 | 39 | updateData := flag.Bool("update", false, "update all prefixes in database and exit") 40 | databasePath := flag.String("dbpath", "./cloudprefixes.db", "path to database file") 41 | 42 | flag.Parse() 43 | 44 | manager, err := db.NewPrefixManager(*databasePath) 45 | if err != nil { 46 | log.Fatalf("Error creating IP range manager: %v", err) 47 | } 48 | defer manager.Close() 49 | 50 | if *updateData { 51 | u := update.NewUpdateManager(manager) 52 | u.UpdateAllSources() 53 | return 54 | } 55 | 56 | // read from argument list if supplied otherwise read from stdin 57 | if flag.NArg() > 0 { 58 | for _, ip := range flag.Args() { 59 | found, info, err := manager.ContainsIP(ip) 60 | if err != nil { 61 | log.Fatalf("error scanning database: %v", err) 62 | } 63 | if found { 64 | b, err := json.Marshal(Results{IP: ip, Info: info}) 65 | if err != nil { 66 | log.Fatalf("error serializing to json: %v", err) 67 | } 68 | fmt.Println(string(b)) 69 | } 70 | } 71 | } else { 72 | scanner := bufio.NewScanner(os.Stdin) 73 | for scanner.Scan() { 74 | ip := scanner.Text() 75 | found, info, err := manager.ContainsIP(ip) 76 | if err != nil { 77 | log.Fatalf("error scanning database: %v", err) 78 | } 79 | if found { 80 | b, err := json.Marshal(Results{IP: ip, Info: info}) 81 | if err != nil { 82 | log.Fatalf("error serializing to json: %v", err) 83 | } 84 | fmt.Println(string(b)) 85 | } 86 | } 87 | 88 | if err = scanner.Err(); err != nil { 89 | log.Fatalf("error reading from stdin: %v", err) 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mchaffe/cloudprefixes 2 | 3 | go 1.21 4 | 5 | require modernc.org/sqlite v1.33.1 6 | 7 | require ( 8 | github.com/dustin/go-humanize v1.0.1 // indirect 9 | github.com/google/uuid v1.6.0 // indirect 10 | github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect 11 | github.com/mattn/go-isatty v0.0.20 // indirect 12 | github.com/ncruces/go-strftime v0.1.9 // indirect 13 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect 14 | golang.org/x/sys v0.22.0 // indirect 15 | modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect 16 | modernc.org/libc v1.55.3 // indirect 17 | modernc.org/mathutil v1.6.0 // indirect 18 | modernc.org/memory v1.8.0 // indirect 19 | modernc.org/strutil v1.2.0 // indirect 20 | modernc.org/token v1.1.0 // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 2 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 3 | github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= 4 | github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= 5 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 6 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 7 | github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= 8 | github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= 9 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 10 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 11 | github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= 12 | github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= 13 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 14 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 15 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= 16 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= 17 | golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= 18 | golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 19 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 20 | golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= 21 | golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 22 | golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= 23 | golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= 24 | modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= 25 | modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= 26 | modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= 27 | modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= 28 | modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= 29 | modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= 30 | modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= 31 | modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= 32 | modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= 33 | modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= 34 | modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= 35 | modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= 36 | modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= 37 | modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= 38 | modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= 39 | modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= 40 | modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= 41 | modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= 42 | modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= 43 | modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= 44 | modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM= 45 | modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k= 46 | modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= 47 | modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= 48 | modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= 49 | modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= 50 | -------------------------------------------------------------------------------- /pkg/db/main.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "database/sql" 5 | "encoding/binary" 6 | "fmt" 7 | "math/big" 8 | "net" 9 | 10 | _ "modernc.org/sqlite" 11 | ) 12 | 13 | type PrefixInfo struct { 14 | Prefix string `json:"prefix"` 15 | Platform string `json:"platform"` 16 | Region *string `json:"region,omitempty"` 17 | Service *string `json:"service,omitempty"` 18 | Metadata *string `json:"metadata,omitempty"` 19 | } 20 | 21 | type PrefixManager struct { 22 | db *sql.DB 23 | } 24 | 25 | func NewPrefixManager(dbPath string) (*PrefixManager, error) { 26 | db, err := sql.Open("sqlite", dbPath) 27 | if err != nil { 28 | return nil, fmt.Errorf("error opening database: %v", err) 29 | } 30 | 31 | manager := &PrefixManager{db: db} 32 | err = manager.initDB() 33 | if err != nil { 34 | db.Close() 35 | return nil, fmt.Errorf("error initializing database: %v", err) 36 | } 37 | 38 | return manager, nil 39 | } 40 | 41 | func (m *PrefixManager) initDB() error { 42 | _, err := m.db.Exec(` 43 | CREATE TABLE IF NOT EXISTS cloud_prefixes ( 44 | id INTEGER PRIMARY KEY AUTOINCREMENT, 45 | service TEXT, 46 | platform TEXT, 47 | region TEXT, 48 | prefix TEXT, 49 | start_ip_high INTEGER, 50 | start_ip_low INTEGER, 51 | end_ip_high INTEGER, 52 | end_ip_low INTEGER, 53 | ip_version INTEGER, 54 | metadata JSONB 55 | ) 56 | `) 57 | return err 58 | } 59 | 60 | func (m *PrefixManager) AddPrefix(info PrefixInfo) error { 61 | _, ipNet, err := net.ParseCIDR(info.Prefix) 62 | if err != nil { 63 | return fmt.Errorf("invalid CIDR: %v", err) 64 | } 65 | 66 | startIPHigh, startIPLow, err := ipToInts(ipNet.IP) 67 | if err != nil { 68 | return err 69 | } 70 | endIPHigh, endIPLow, err := ipToInts(lastIP(ipNet)) 71 | if err != nil { 72 | return err 73 | } 74 | ipVersion := 4 75 | if ipNet.IP.To4() == nil { 76 | ipVersion = 6 77 | } 78 | 79 | _, err = m.db.Exec(` 80 | INSERT OR REPLACE INTO cloud_prefixes 81 | (prefix, start_ip_high, start_ip_low, end_ip_high, end_ip_low, ip_version, region, platform, service, metadata) 82 | VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, 83 | info.Prefix, startIPHigh, startIPLow, endIPHigh, endIPLow, ipVersion, info.Region, info.Platform, info.Service, info.Metadata) 84 | return err 85 | } 86 | 87 | func (m *PrefixManager) AddPrefixBatch(infos []PrefixInfo) error { 88 | tx, err := m.db.Begin() 89 | if err != nil { 90 | return err 91 | } 92 | defer tx.Rollback() 93 | 94 | stmt, err := tx.Prepare(` 95 | INSERT OR REPLACE INTO cloud_prefixes 96 | (prefix, start_ip_high, start_ip_low, end_ip_high, end_ip_low, ip_version, region, platform, service, metadata) 97 | VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 98 | `) 99 | if err != nil { 100 | return err 101 | } 102 | defer stmt.Close() 103 | 104 | for _, info := range infos { 105 | _, ipNet, err := net.ParseCIDR(info.Prefix) 106 | if err != nil { 107 | return fmt.Errorf("invalid CIDR %s: %v", info.Prefix, err) 108 | } 109 | 110 | startIPHigh, startIPLow, err := ipToInts(ipNet.IP) 111 | if err != nil { 112 | return err 113 | } 114 | endIPHigh, endIPLow, err := ipToInts(lastIP(ipNet)) 115 | if err != nil { 116 | return err 117 | } 118 | ipVersion := 4 119 | if ipNet.IP.To4() == nil { 120 | ipVersion = 6 121 | } 122 | 123 | _, err = stmt.Exec(info.Prefix, startIPHigh, startIPLow, endIPHigh, endIPLow, ipVersion, info.Region, info.Platform, info.Service, info.Metadata) 124 | if err != nil { 125 | return err 126 | } 127 | } 128 | 129 | return tx.Commit() 130 | } 131 | 132 | func (m *PrefixManager) ContainsIP(ip string) (bool, []PrefixInfo, error) { 133 | parsedIP := net.ParseIP(ip) 134 | if parsedIP == nil { 135 | return false, []PrefixInfo{}, fmt.Errorf("invalid IP address") 136 | } 137 | 138 | ipHigh, ipLow, err := ipToInts(parsedIP) 139 | if err != nil { 140 | return false, []PrefixInfo{}, err 141 | } 142 | 143 | ipVersion := 4 144 | if parsedIP.To4() == nil { 145 | ipVersion = 6 146 | } 147 | 148 | rows, err := m.db.Query(` 149 | SELECT prefix, region, platform, service, metadata 150 | FROM cloud_prefixes 151 | WHERE start_ip_high <= ? AND start_ip_low <= ? 152 | AND end_ip_high >= ? AND end_ip_low >= ? 153 | AND ip_version = ?`, 154 | ipHigh, ipLow, ipHigh, ipLow, ipVersion) 155 | if err != nil { 156 | return false, []PrefixInfo{}, err 157 | } 158 | 159 | var results []PrefixInfo 160 | for rows.Next() { 161 | var info PrefixInfo 162 | if err := rows.Scan(&info.Prefix, &info.Region, &info.Platform, &info.Service, &info.Metadata); err != nil { 163 | return false, []PrefixInfo{}, err 164 | } 165 | results = append(results, info) 166 | } 167 | // Check for errors from iterating over rows. 168 | if err := rows.Err(); err != nil { 169 | return false, []PrefixInfo{}, err 170 | } 171 | 172 | // Check if no results were found 173 | if len(results) == 0 { 174 | return false, []PrefixInfo{}, nil 175 | } 176 | 177 | return true, results, nil 178 | } 179 | 180 | func (m *PrefixManager) Close() error { 181 | return m.db.Close() 182 | } 183 | 184 | // SQLite doesn't have 128bit integers or dedicated IP type. So in order to store 185 | // them in a way to make querying efficient, split them into two 64bit integers 186 | func ipToInts(ip net.IP) (high uint64, low uint64, err error) { 187 | if ip == nil { 188 | return 0, 0, fmt.Errorf("nil IP address") 189 | } 190 | 191 | ipv4 := ip.To4() 192 | if ipv4 != nil { 193 | // Handle IPv4 194 | return 0, uint64(binary.BigEndian.Uint32(ipv4)), nil 195 | } 196 | 197 | // Handle IPv6 198 | ipv6 := ip.To16() 199 | if ipv6 == nil { 200 | return 0, 0, fmt.Errorf("invalid IP address") 201 | } 202 | 203 | ipInt := new(big.Int).SetBytes(ipv6) 204 | high = ipInt.Rsh(ipInt, 64).Uint64() 205 | low = ipInt.Uint64() 206 | 207 | return high, low, nil 208 | } 209 | 210 | func lastIP(ipNet *net.IPNet) net.IP { 211 | lastIP := make(net.IP, len(ipNet.IP)) 212 | copy(lastIP, ipNet.IP) 213 | for i := range lastIP { 214 | lastIP[i] |= ^ipNet.Mask[i] 215 | } 216 | return lastIP 217 | } 218 | 219 | func (m *PrefixManager) ClearAllData() error { 220 | _, err := m.db.Exec("DELETE FROM cloud_prefixes") 221 | if err != nil { 222 | return fmt.Errorf("failed to clear database: %v", err) 223 | } 224 | return nil 225 | } 226 | -------------------------------------------------------------------------------- /pkg/db/main_test.go: -------------------------------------------------------------------------------- 1 | package db 2 | 3 | import ( 4 | "net" 5 | "reflect" 6 | "testing" 7 | 8 | _ "modernc.org/sqlite" 9 | ) 10 | 11 | func stringPointer(s string) *string { 12 | return &s 13 | } 14 | 15 | func TestPrefixManager_AddPrefix(t *testing.T) { 16 | // Create a temporary in-memory database for testing 17 | manager, err := NewPrefixManager(":memory:") 18 | if err != nil { 19 | t.Fatalf("Failed to create IPRangeManager: %v", err) 20 | } 21 | defer manager.Close() 22 | 23 | // Initialize test cases 24 | tests := []struct { 25 | name string 26 | info PrefixInfo 27 | wantErr bool 28 | }{ 29 | { 30 | name: "Valid IPv4 CIDR", 31 | info: PrefixInfo{ 32 | Prefix: "192.168.1.0/24", 33 | Platform: "AWS", 34 | Region: stringPointer("us-east-1"), 35 | Service: stringPointer("EC2"), 36 | }, 37 | wantErr: false, 38 | }, 39 | { 40 | name: "Valid IPv6 CIDR", 41 | info: PrefixInfo{ 42 | Prefix: "2001:db8::/32", 43 | Platform: "GCP", 44 | Region: stringPointer("global"), 45 | Service: stringPointer("Compute"), 46 | }, 47 | wantErr: false, 48 | }, 49 | { 50 | name: "Invalid CIDR", 51 | info: PrefixInfo{ 52 | Prefix: "invalid_cidr", 53 | Platform: "AWS", 54 | Region: stringPointer("us-west-2"), 55 | Service: stringPointer("S3"), 56 | }, 57 | wantErr: true, 58 | }, 59 | } 60 | 61 | for _, tt := range tests { 62 | t.Run(tt.name, func(t *testing.T) { 63 | if err := manager.AddPrefix(tt.info); (err != nil) != tt.wantErr { 64 | t.Errorf("PrefixManager.AddPrefix() error = %v, wantErr %v", err, tt.wantErr) 65 | } 66 | }) 67 | } 68 | } 69 | 70 | func TestPrefixManager_AddPrefixBatch(t *testing.T) { 71 | manager, err := NewPrefixManager(":memory:") 72 | if err != nil { 73 | t.Fatalf("Failed to create IPRangeManager: %v", err) 74 | } 75 | defer manager.Close() 76 | 77 | tests := []struct { 78 | name string 79 | infos []PrefixInfo 80 | wantErr bool 81 | }{ 82 | { 83 | name: "Valid Batch of Prefixes", 84 | infos: []PrefixInfo{ 85 | { 86 | Prefix: "192.168.2.0/24", 87 | Platform: "AWS", 88 | Region: stringPointer("us-east-1"), 89 | Service: stringPointer("EC2"), 90 | }, 91 | { 92 | Prefix: "2001:db8::/32", 93 | Platform: "Azure", 94 | Region: stringPointer("global"), 95 | Service: stringPointer("VM"), 96 | }, 97 | }, 98 | wantErr: false, 99 | }, 100 | { 101 | name: "Invalid CIDR in Batch", 102 | infos: []PrefixInfo{ 103 | { 104 | Prefix: "invalid_cidr", 105 | Platform: "GCP", 106 | Region: stringPointer("us-central1"), 107 | Service: stringPointer("Kubernetes"), 108 | }, 109 | }, 110 | wantErr: true, 111 | }, 112 | } 113 | 114 | for _, tt := range tests { 115 | t.Run(tt.name, func(t *testing.T) { 116 | if err := manager.AddPrefixBatch(tt.infos); (err != nil) != tt.wantErr { 117 | t.Errorf("PrefixManager.AddPrefixBatch() error = %v, wantErr %v", err, tt.wantErr) 118 | } 119 | }) 120 | } 121 | } 122 | 123 | func TestPrefixManager_ContainsIP(t *testing.T) { 124 | manager, err := NewPrefixManager(":memory:") 125 | if err != nil { 126 | t.Fatalf("Failed to create IPRangeManager: %v", err) 127 | } 128 | defer manager.Close() 129 | 130 | // Pre-populate database with known prefixes 131 | err = manager.AddPrefix(PrefixInfo{ 132 | Prefix: "192.168.3.0/24", 133 | Platform: "AWS", 134 | Region: stringPointer("us-east-1"), 135 | Service: stringPointer("EC2"), 136 | }) 137 | if err != nil { 138 | t.Fatalf("Failed to add prefix: %v", err) 139 | } 140 | 141 | err = manager.AddPrefix(PrefixInfo{ 142 | Prefix: "2001:db8::/32", 143 | Platform: "Azure", 144 | Region: stringPointer("global"), 145 | Service: stringPointer("VM"), 146 | }) 147 | if err != nil { 148 | t.Fatalf("Failed to add prefix: %v", err) 149 | } 150 | 151 | tests := []struct { 152 | name string 153 | ip string 154 | want bool 155 | wantErr bool 156 | expected int // Expected number of prefixes in result 157 | }{ 158 | {"IP inside IPv4 range", "192.168.3.10", true, false, 1}, 159 | {"IP inside IPv6 range", "2001:db8::1", true, false, 1}, 160 | {"IP outside range", "203.0.113.5", false, false, 0}, 161 | {"Invalid IP", "invalid_ip", false, true, 0}, 162 | } 163 | 164 | for _, tt := range tests { 165 | t.Run(tt.name, func(t *testing.T) { 166 | got, results, err := manager.ContainsIP(tt.ip) 167 | if (err != nil) != tt.wantErr { 168 | t.Errorf("PrefixManager.ContainsIP() error = %v, wantErr %v", err, tt.wantErr) 169 | return 170 | } 171 | if got != tt.want { 172 | t.Errorf("PrefixManager.ContainsIP() = %v, want %v", got, tt.want) 173 | } 174 | if len(results) != tt.expected { 175 | t.Errorf("Expected %d prefixes, but got %d", tt.expected, len(results)) 176 | } 177 | }) 178 | } 179 | } 180 | 181 | func Test_ipToInts(t *testing.T) { 182 | tests := []struct { 183 | name string 184 | ip net.IP 185 | wantHigh uint64 186 | wantLow uint64 187 | wantErr bool 188 | }{ 189 | {"IPv4", net.ParseIP("203.0.113.1").To4(), 0, 3405803777, false}, 190 | {"IPv6", net.ParseIP("2001:db8::1").To16(), 2306139568115548160, 2306139568115548160, false}, 191 | } 192 | for _, tt := range tests { 193 | t.Run(tt.name, func(t *testing.T) { 194 | gotHigh, gotLow, err := ipToInts(tt.ip) 195 | if (err != nil) != tt.wantErr { 196 | t.Errorf("ipToInts() error = %v, wantErr %v", err, tt.wantErr) 197 | return 198 | } 199 | if gotHigh != tt.wantHigh { 200 | t.Errorf("ipToInts() gotHigh = %v, want %v", gotHigh, tt.wantHigh) 201 | } 202 | if gotLow != tt.wantLow { 203 | t.Errorf("ipToInts() gotLow = %v, want %v", gotLow, tt.wantLow) 204 | } 205 | }) 206 | } 207 | } 208 | 209 | func Test_lastIP(t *testing.T) { 210 | tests := []struct { 211 | name string 212 | ipNet *net.IPNet 213 | want net.IP 214 | }{ 215 | { 216 | "IPv4", 217 | &net.IPNet{IP: net.IPv4(203, 0, 113, 0).To4(), Mask: net.CIDRMask(24, 32)}, 218 | net.IPv4(203, 0, 113, 255).To4(), 219 | }, 220 | { 221 | "IPv6", 222 | &net.IPNet{IP: net.ParseIP("2001:db8::").To16(), Mask: net.CIDRMask(64, 128)}, 223 | net.ParseIP("2001:db8::ffff:ffff:ffff:ffff").To16(), 224 | }, 225 | } 226 | for _, tt := range tests { 227 | t.Run(tt.name, func(t *testing.T) { 228 | if got := lastIP(tt.ipNet); !reflect.DeepEqual(got, tt.want) { 229 | t.Errorf("lastIP() = %v, want %v", got, tt.want) 230 | } 231 | }) 232 | } 233 | } 234 | 235 | func TestPrefixManager_ClearAllData(t *testing.T) { 236 | manager, err := NewPrefixManager(":memory:") 237 | if err != nil { 238 | t.Fatalf("Failed to create IPRangeManager: %v", err) 239 | } 240 | defer manager.Close() 241 | 242 | // Pre-populate database with known prefixes 243 | err = manager.AddPrefix(PrefixInfo{ 244 | Prefix: "192.168.4.0/24", 245 | Platform: "AWS", 246 | Region: stringPointer("us-east-1"), 247 | Service: stringPointer("EC2"), 248 | }) 249 | if err != nil { 250 | t.Fatalf("Failed to add prefix: %v", err) 251 | } 252 | 253 | tests := []struct { 254 | name string 255 | m *PrefixManager 256 | wantErr bool 257 | }{ 258 | { 259 | name: "Clear Data", 260 | m: manager, 261 | wantErr: false, 262 | }, 263 | } 264 | 265 | for _, tt := range tests { 266 | t.Run(tt.name, func(t *testing.T) { 267 | if err := tt.m.ClearAllData(); (err != nil) != tt.wantErr { 268 | t.Errorf("PrefixManager.ClearAllData() error = %v, wantErr %v", err, tt.wantErr) 269 | } 270 | 271 | // Ensure the data is cleared 272 | _, results, err := tt.m.ContainsIP("192.168.4.10") 273 | if err != nil { 274 | t.Fatalf("Failed to check IP after clear: %v", err) 275 | } 276 | if len(results) != 0 { 277 | t.Errorf("Expected no prefixes after clearing data, but found %d", len(results)) 278 | } 279 | }) 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /pkg/update/aws.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/mchaffe/cloudprefixes/pkg/db" 7 | ) 8 | 9 | type AwsResponse struct { 10 | SyncToken string `json:"syncToken"` 11 | CreateDate string `json:"createDate"` 12 | Prefixes []struct { 13 | IPPrefix string `json:"ip_prefix"` 14 | Region *string `json:"region"` 15 | Service *string `json:"service"` 16 | NetworkBorderGroup string `json:"network_border_group"` 17 | } `json:"prefixes"` 18 | Ipv6Prefixes []struct { 19 | Ipv6Prefix string `json:"ipv6_prefix"` 20 | Region *string `json:"region"` 21 | Service *string `json:"service"` 22 | NetworkBorderGroup string `json:"network_border_group"` 23 | } `json:"ipv6_prefixes"` 24 | } 25 | 26 | func (m *UpdateManager) UpdateAwsPrefixes(url string) error { 27 | body, err := GetJson(url) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | var j AwsResponse 33 | err = json.Unmarshal(body, &j) 34 | if err != nil { 35 | return err 36 | } 37 | 38 | var prefixes []db.PrefixInfo 39 | for _, prefix := range j.Prefixes { 40 | metaMap := map[string]string{ 41 | "network_boarder_group": prefix.NetworkBorderGroup, 42 | } 43 | metaJSON, err := json.Marshal(metaMap) 44 | if err != nil { 45 | return err 46 | } 47 | metaStr := string(metaJSON) 48 | 49 | prefixes = append(prefixes, db.PrefixInfo{ 50 | Platform: "AWS", 51 | Region: prefix.Region, 52 | Service: prefix.Service, 53 | Prefix: prefix.IPPrefix, 54 | Metadata: &metaStr, 55 | }) 56 | } 57 | for _, prefix := range j.Ipv6Prefixes { 58 | metaMap := map[string]string{ 59 | "network_boarder_group": prefix.NetworkBorderGroup, 60 | } 61 | metaJSON, err := json.Marshal(metaMap) 62 | if err != nil { 63 | return err 64 | } 65 | metaStr := string(metaJSON) 66 | 67 | prefixes = append(prefixes, db.PrefixInfo{ 68 | Platform: "AWS", 69 | Region: prefix.Region, 70 | Service: prefix.Service, 71 | Prefix: prefix.Ipv6Prefix, 72 | Metadata: &metaStr, 73 | }) 74 | } 75 | 76 | return m.InsertPrefixes(prefixes) 77 | } 78 | -------------------------------------------------------------------------------- /pkg/update/aws_test.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import "testing" 4 | 5 | func TestUpdateManager_UpdateAwsPrefixes(t *testing.T) { 6 | manager, ts, cleanup := SetupUpdateManager() 7 | defer cleanup() 8 | 9 | tests := []struct { 10 | name string 11 | m *UpdateManager 12 | url string 13 | wantErr bool 14 | }{ 15 | {"working", manager, ts.URL() + "/aws_response.json", false}, 16 | } 17 | for _, tt := range tests { 18 | t.Run(tt.name, func(t *testing.T) { 19 | if err := tt.m.UpdateAwsPrefixes(tt.url); (err != nil) != tt.wantErr { 20 | t.Errorf("UpdateManager.UpdateAwsPrefixes() error = %v, wantErr %v", err, tt.wantErr) 21 | } 22 | found, prefixes, err := manager.PrefixManager.ContainsIP("2600:1f18:6fe3:8c00::1") 23 | if err != nil { 24 | t.Fatalf("failed to query prefixes: %v", err) 25 | } 26 | 27 | if !found && len(prefixes) != 2 { 28 | t.Errorf("UpdateManager.UpdateAzurePrefixes() len = %d, wanted 2", len(prefixes)) 29 | } 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pkg/update/azure.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log/slog" 7 | "regexp" 8 | 9 | "github.com/mchaffe/cloudprefixes/pkg/db" 10 | ) 11 | 12 | type AzureResponse struct { 13 | ChangeNumber int `json:"changeNumber"` 14 | Cloud string `json:"cloud"` 15 | Values []struct { 16 | Name string `json:"name"` 17 | ID string `json:"id"` 18 | NetworkFeatures []string `json:"networkFeatures"` 19 | Properties struct { 20 | ChangeNumber int `json:"changeNumber"` 21 | Region *string `json:"region"` 22 | RegionID int `json:"regionId"` 23 | Platform string `json:"platform"` 24 | SystemService *string `json:"systemService"` 25 | AddressPrefixes []string `json:"addressPrefixes"` 26 | } `json:"properties"` 27 | } `json:"values"` 28 | } 29 | 30 | type URLFinder interface { 31 | FindURL(body []byte) (string, error) 32 | } 33 | 34 | type MicrosoftURLFinder struct{} 35 | 36 | func (f *MicrosoftURLFinder) FindURL(body []byte) (string, error) { 37 | re := regexp.MustCompile(`(?m)https:\/\/download\.microsoft\.com\/download\/.*?\.json`) 38 | match := re.Find(body) 39 | if match == nil { 40 | slog.Debug("HTML body", "body", string(body)) 41 | return "", fmt.Errorf("unable to match URL in html response") 42 | } 43 | return string(match), nil 44 | } 45 | 46 | func (m *UpdateManager) UpdateAzurePrefixes(url string) error { 47 | slog.Info("fetching HTML to find JSON", "url", url) 48 | jsonUrl, err := GetJsonUrl(url, &MicrosoftURLFinder{}) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | slog.Info("fetching JSON", "url", url) 54 | body, err := GetJson(jsonUrl) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | var j AzureResponse 60 | err = json.Unmarshal(body, &j) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | var prefixes []db.PrefixInfo 66 | for _, value := range j.Values { 67 | region := value.Properties.Region 68 | if region != nil { 69 | *region = "global" 70 | } 71 | for _, addressPrefix := range value.Properties.AddressPrefixes { 72 | prefixes = append(prefixes, db.PrefixInfo{ 73 | Platform: "Azure", 74 | Region: region, 75 | Service: value.Properties.SystemService, 76 | Prefix: addressPrefix, 77 | }) 78 | } 79 | } 80 | return m.InsertPrefixes(prefixes) 81 | } 82 | -------------------------------------------------------------------------------- /pkg/update/azure_test.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | 8 | "github.com/mchaffe/cloudprefixes/pkg/db" 9 | ) 10 | 11 | func TestMicrosoftURLFinder_FindURL(t *testing.T) { 12 | html, err := os.ReadFile("testdata/azure_response.html") 13 | if err != nil { 14 | t.Error(err) 15 | } 16 | tests := []struct { 17 | name string 18 | f *MicrosoftURLFinder 19 | body []byte 20 | want string 21 | wantErr bool 22 | }{ 23 | { 24 | "Match found", 25 | &MicrosoftURLFinder{}, 26 | html, 27 | "https://download.microsoft.com/download/7/1/D/71D86715-5596-4529-9B13-DA13A5DE5B63/ServiceTags_Public_20240923.json", 28 | false, 29 | }, 30 | { 31 | "No Match", 32 | &MicrosoftURLFinder{}, 33 | []byte("nope"), 34 | "", 35 | true, 36 | }, 37 | } 38 | for _, tt := range tests { 39 | t.Run(tt.name, func(t *testing.T) { 40 | got, err := tt.f.FindURL(tt.body) 41 | if (err != nil) != tt.wantErr { 42 | t.Errorf("MicrosoftURLFinder.FindURL() error = %v, wantErr %v", err, tt.wantErr) 43 | return 44 | } 45 | if got != tt.want { 46 | t.Errorf("MicrosoftURLFinder.FindURL() = %v, want %v", got, tt.want) 47 | } 48 | }) 49 | } 50 | } 51 | 52 | func TestUpdateManager_UpdateAzurePrefixes(t *testing.T) { 53 | // Create a new test server 54 | ts := NewTestServer() 55 | defer ts.Close() 56 | 57 | // Mock function for GetJsonUrl 58 | mockGetJsonUrl := func(url string, finder URLFinder) (string, error) { 59 | return fmt.Sprintf("%s/azure_response.json", ts.URL()), nil 60 | } 61 | 62 | // Create a temporary file for the database 63 | f, err := os.CreateTemp("", "test_cloudprefixes.db") 64 | if err != nil { 65 | panic(err) 66 | } 67 | defer os.Remove((f.Name())) 68 | 69 | // Initialize IPRangeManager with the temporary database file 70 | dm, err := db.NewPrefixManager(f.Name()) 71 | if err != nil { 72 | panic(err) 73 | } 74 | 75 | // Create the UpdateManager 76 | manager := &UpdateManager{ 77 | PrefixManager: dm, 78 | GetJsonUrl: mockGetJsonUrl, 79 | } 80 | 81 | tests := []struct { 82 | name string 83 | m *UpdateManager 84 | url string 85 | wantErr bool 86 | }{ 87 | {"working", manager, ts.URL() + "/azure_response.html", false}, 88 | } 89 | for _, tt := range tests { 90 | t.Run(tt.name, func(t *testing.T) { 91 | if err := tt.m.UpdateAzurePrefixes(tt.url); (err != nil) != tt.wantErr { 92 | t.Errorf("UpdateManager.UpdateAzurePrefixes() error = %v, wantErr %v", err, tt.wantErr) 93 | } 94 | found, prefixes, err := manager.PrefixManager.ContainsIP("13.69.109.133") 95 | if err != nil { 96 | t.Fatalf("failed to query prefixes: %v", err) 97 | } 98 | 99 | if !found && len(prefixes) != 4 { 100 | t.Errorf("UpdateManager.UpdateAzurePrefixes() len = %d, wanted 4", len(prefixes)) 101 | } 102 | }) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /pkg/update/export_tests.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/mchaffe/cloudprefixes/pkg/db" 11 | ) 12 | 13 | func stringPointer(s string) *string { 14 | return &s 15 | } 16 | 17 | // TestServer represents a local HTTP server for testing 18 | type TestServer struct { 19 | Server *httptest.Server 20 | } 21 | 22 | // NewTestServer creates and starts a new test server 23 | func NewTestServer() *TestServer { 24 | mux := http.NewServeMux() 25 | mux.HandleFunc("/", handleTestData) 26 | 27 | server := httptest.NewServer(mux) 28 | return &TestServer{Server: server} 29 | } 30 | 31 | // Close shuts down the test server 32 | func (ts *TestServer) Close() { 33 | ts.Server.Close() 34 | } 35 | 36 | // URL returns the base URL of the test server 37 | func (ts *TestServer) URL() string { 38 | return ts.Server.URL 39 | } 40 | 41 | // handleTestData serves files from the testdata directory 42 | func handleTestData(w http.ResponseWriter, r *http.Request) { 43 | filePath := filepath.Join("testdata", r.URL.Path) 44 | content, err := os.ReadFile(filePath) 45 | if err != nil { 46 | http.Error(w, fmt.Sprintf("File not found: %s", r.URL.Path), http.StatusNotFound) 47 | return 48 | } 49 | 50 | w.WriteHeader(http.StatusOK) 51 | w.Write(content) 52 | } 53 | 54 | func SetupUpdateManager() (*UpdateManager, *TestServer, func()) { 55 | // Create a new test server 56 | ts := NewTestServer() 57 | 58 | // Initialize IPRangeManager with the temporary database 59 | dm, err := db.NewPrefixManager(":memory:") 60 | if err != nil { 61 | panic(err) 62 | } 63 | 64 | // Create the UpdateManager 65 | manager := &UpdateManager{ 66 | PrefixManager: dm, 67 | GetJsonUrl: GetJsonUrl, 68 | } 69 | 70 | // Return manager, test server, and cleanup function 71 | return manager, ts, func() { 72 | ts.Close() 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pkg/update/geofeed.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "encoding/csv" 5 | "encoding/json" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | 10 | "github.com/mchaffe/cloudprefixes/pkg/db" 11 | ) 12 | 13 | type Geofeed struct { 14 | Prefix string `json:"-"` 15 | CountryCode *string `json:"country_code,omitempty"` 16 | RegionCode *string `json:"region_code,omitempty"` 17 | City *string `json:"city,omitempty"` 18 | Postal *string `json:"postal,omitempty"` 19 | } 20 | 21 | // Helper function to handle optional string fields in the CSV 22 | func optionalString(record []string, index int) *string { 23 | if len(record) > index && record[index] != "" { 24 | return &record[index] 25 | } 26 | return nil 27 | } 28 | 29 | func (m *UpdateManager) UpdateGeoFeedPrefixes(url string, platform string) error { 30 | res, err := http.Get(url) 31 | if err != nil { 32 | return err 33 | } 34 | defer res.Body.Close() 35 | 36 | if res.StatusCode != 200 { 37 | return fmt.Errorf("status code error: %d %s", res.StatusCode, res.Status) 38 | } 39 | 40 | var prefixes []db.PrefixInfo 41 | 42 | reader := csv.NewReader(res.Body) 43 | reader.Comma = ',' 44 | 45 | for { 46 | record, err := reader.Read() 47 | if err == io.EOF { 48 | break 49 | } 50 | if err != nil { 51 | return fmt.Errorf("error reading CSV: %v", err) 52 | } 53 | 54 | if len(record) == 0 { 55 | continue 56 | } 57 | 58 | location := Geofeed{ 59 | CountryCode: optionalString(record, 1), 60 | RegionCode: optionalString(record, 2), 61 | City: optionalString(record, 3), 62 | Postal: optionalString(record, 4), 63 | } 64 | 65 | metaMap := map[string]Geofeed{ 66 | "location": location, 67 | } 68 | metaJSON, err := json.Marshal(metaMap) 69 | if err != nil { 70 | return err 71 | } 72 | metaStr := string(metaJSON) 73 | 74 | prefixes = append(prefixes, db.PrefixInfo{ 75 | Prefix: record[0], 76 | Platform: platform, 77 | Metadata: &metaStr, 78 | }) 79 | } 80 | 81 | return m.InsertPrefixes(prefixes) 82 | } 83 | -------------------------------------------------------------------------------- /pkg/update/geofeed_test.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func Test_optionalString(t *testing.T) { 9 | type args struct { 10 | record []string 11 | index int 12 | } 13 | tests := []struct { 14 | name string 15 | args args 16 | want *string 17 | }{ 18 | // TODO: Add test cases. 19 | } 20 | for _, tt := range tests { 21 | t.Run(tt.name, func(t *testing.T) { 22 | if got := optionalString(tt.args.record, tt.args.index); !reflect.DeepEqual(got, tt.want) { 23 | t.Errorf("optionalString() = %v, want %v", got, tt.want) 24 | } 25 | }) 26 | } 27 | } 28 | 29 | func TestUpdateManager_UpdateGeoFeedPrefixes(t *testing.T) { 30 | manager, ts, cleanup := SetupUpdateManager() 31 | defer cleanup() 32 | 33 | tests := []struct { 34 | name string 35 | m *UpdateManager 36 | url string 37 | wantErr bool 38 | }{ 39 | {"working", manager, ts.URL() + "/digitalocean_response.csv", false}, 40 | } 41 | for _, tt := range tests { 42 | t.Run(tt.name, func(t *testing.T) { 43 | if err := tt.m.UpdateGeoFeedPrefixes(tt.url, "Digital Ocean"); (err != nil) != tt.wantErr { 44 | t.Errorf("UpdateManager.UpdateGeoFeedPrefixes() error = %v, wantErr %v", err, tt.wantErr) 45 | } 46 | found, prefixes, err := manager.PrefixManager.ContainsIP("45.55.32.1") 47 | if err != nil { 48 | t.Fatalf("failed to query prefixes: %v", err) 49 | } 50 | 51 | if !found && len(prefixes) != 1 { 52 | t.Errorf("UpdateManager.UpdateAzurePrefixes() len = %d, wanted 1", len(prefixes)) 53 | } 54 | }) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pkg/update/github.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "encoding/json" 5 | "net" 6 | "reflect" 7 | 8 | "github.com/mchaffe/cloudprefixes/pkg/db" 9 | 10 | "log/slog" 11 | ) 12 | 13 | type GithubResponse struct { 14 | VerifiablePasswordAuthentication bool `json:"verifiable_password_authentication"` 15 | SSHKeyFingerprints struct { 16 | Sha256Ecdsa string `json:"SHA256_ECDSA"` 17 | Sha256Ed25519 string `json:"SHA256_ED25519"` 18 | Sha256Rsa string `json:"SHA256_RSA"` 19 | } `json:"ssh_key_fingerprints"` 20 | SSHKeys []string `json:"ssh_keys"` 21 | Hooks []string `json:"hooks"` 22 | Web []string `json:"web"` 23 | API []string `json:"api"` 24 | Git []string `json:"git"` 25 | GithubEnterpriseImporter []string `json:"github_enterprise_importer"` 26 | Packages []string `json:"packages"` 27 | Pages []string `json:"pages"` 28 | Importer []string `json:"importer"` 29 | Actions []string `json:"actions"` 30 | ActionsMacos []string `json:"actions_macos"` 31 | Codespaces []string `json:"codespaces"` 32 | Dependabot []string `json:"dependabot"` 33 | Copilot []string `json:"copilot"` 34 | Domains struct { 35 | Website []string `json:"website"` 36 | Codespaces []string `json:"codespaces"` 37 | Copilot []string `json:"copilot"` 38 | Packages []string `json:"packages"` 39 | Actions []string `json:"actions"` 40 | ArtifactAttestations struct { 41 | TrustDomain string `json:"trust_domain"` 42 | Services []string `json:"services"` 43 | } `json:"artifact_attestations"` 44 | } `json:"domains"` 45 | } 46 | 47 | func iterateCIDRFields(g GithubResponse) (prefixes []db.PrefixInfo) { 48 | v := reflect.ValueOf(g) 49 | t := v.Type() 50 | 51 | for i := 0; i < v.NumField(); i++ { 52 | field := v.Field(i) 53 | fieldType := t.Field(i) 54 | 55 | if field.Kind() == reflect.Slice && field.Type().Elem().Kind() == reflect.String { 56 | slice := field.Interface().([]string) 57 | if len(slice) > 0 && isCIDR(slice[0]) { 58 | slog.Info("Field contains CIDRs:", "field", fieldType.Name) 59 | for _, cidr := range slice { 60 | prefixes = append(prefixes, db.PrefixInfo{ 61 | Platform: "GitHub", 62 | Prefix: cidr, 63 | Service: &fieldType.Name, 64 | }) 65 | } 66 | } 67 | } 68 | } 69 | return prefixes 70 | } 71 | 72 | func isCIDR(s string) bool { 73 | _, _, err := net.ParseCIDR(s) 74 | return err == nil 75 | } 76 | 77 | func (m *UpdateManager) UpdateGithubPrefixes(url string) error { 78 | body, err := GetJson(url) 79 | if err != nil { 80 | return err 81 | } 82 | 83 | var j GithubResponse 84 | err = json.Unmarshal(body, &j) 85 | if err != nil { 86 | return err 87 | } 88 | 89 | prefixes := iterateCIDRFields(j) 90 | 91 | return m.InsertPrefixes(prefixes) 92 | } 93 | -------------------------------------------------------------------------------- /pkg/update/github_test.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestUpdateManager_UpdateGithubPrefixes(t *testing.T) { 8 | manager, ts, cleanup := SetupUpdateManager() 9 | defer cleanup() 10 | 11 | tests := []struct { 12 | name string 13 | m *UpdateManager 14 | url string 15 | wantErr bool 16 | }{ 17 | {"working", manager, ts.URL() + "/github_response.json", false}, 18 | } 19 | for _, tt := range tests { 20 | t.Run(tt.name, func(t *testing.T) { 21 | if err := tt.m.UpdateGithubPrefixes(tt.url); (err != nil) != tt.wantErr { 22 | t.Errorf("UpdateManager.UpdateGithubPrefixes() error = %v, wantErr %v", err, tt.wantErr) 23 | } 24 | found, prefixes, err := manager.PrefixManager.ContainsIP("13.69.109.133") 25 | if err != nil { 26 | t.Fatalf("failed to query prefixes: %v", err) 27 | } 28 | 29 | if !found && len(prefixes) != 1 { 30 | t.Errorf("UpdateManager.UpdateAzurePrefixes() len = %d, wanted 1", len(prefixes)) 31 | } 32 | }) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pkg/update/google.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | 7 | "github.com/mchaffe/cloudprefixes/pkg/db" 8 | ) 9 | 10 | type GoogleResponse struct { 11 | SyncToken string `json:"synctoken"` 12 | CreationTime string `json:"creationTime"` 13 | Prefixes []struct { 14 | Region *string `json:"scaope"` 15 | Service *string `json:"service"` 16 | IPv4Prefix string `json:"ipv4Prefix"` 17 | IPv6Prefix string `json:"ipv6Prefix"` 18 | } `json:"prefixes"` 19 | } 20 | 21 | func (m *UpdateManager) UpdateGooglePrefixes(url string, platform string) error { 22 | body, err := GetJson(url) 23 | if err != nil { 24 | return err 25 | } 26 | 27 | var j GoogleResponse 28 | err = json.Unmarshal(body, &j) 29 | if err != nil { 30 | return err 31 | } 32 | 33 | var prefixes []db.PrefixInfo 34 | for _, p := range j.Prefixes { 35 | var prefix string 36 | if p.IPv4Prefix != "" { 37 | prefix = p.IPv4Prefix 38 | } else if p.IPv6Prefix != "" { 39 | prefix = p.IPv6Prefix 40 | } else { 41 | return fmt.Errorf("unable to find prefix") 42 | } 43 | prefixes = append(prefixes, db.PrefixInfo{ 44 | Platform: platform, 45 | Region: p.Region, 46 | Service: p.Service, 47 | Prefix: prefix, 48 | }) 49 | } 50 | 51 | return m.InsertPrefixes(prefixes) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/update/google_test.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import "testing" 4 | 5 | func TestUpdateManager_UpdateGooglePrefixes(t *testing.T) { 6 | manager, ts, cleanup := SetupUpdateManager() 7 | defer cleanup() 8 | 9 | tests := []struct { 10 | name string 11 | m *UpdateManager 12 | url string 13 | wantErr bool 14 | }{ 15 | {"working", manager, ts.URL() + "/google_response.json", false}, 16 | } 17 | for _, tt := range tests { 18 | t.Run(tt.name, func(t *testing.T) { 19 | if err := tt.m.UpdateGooglePrefixes(tt.url, "Google Cloud"); (err != nil) != tt.wantErr { 20 | t.Errorf("UpdateManager.UpdateOraclePrefixes() error = %v, wantErr %v", err, tt.wantErr) 21 | } 22 | found, prefixes, err := manager.PrefixManager.ContainsIP("2600:1900:8000::1") 23 | if err != nil { 24 | t.Fatalf("failed to query prefixes: %v", err) 25 | } 26 | 27 | if !found && len(prefixes) != 2 { 28 | t.Errorf("UpdateManager.UpdateAzurePrefixes() len = %d, wanted 2", len(prefixes)) 29 | } 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pkg/update/main.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "log/slog" 8 | "net/http" 9 | 10 | "github.com/mchaffe/cloudprefixes/pkg/db" 11 | ) 12 | 13 | type UpdateManager struct { 14 | PrefixManager *db.PrefixManager 15 | GetJsonUrl func(string, URLFinder) (string, error) // Dependency injection 16 | } 17 | 18 | func NewUpdateManager(prefixManager *db.PrefixManager) *UpdateManager { 19 | return &UpdateManager{PrefixManager: prefixManager} 20 | } 21 | 22 | func GetJsonUrl(url string, finder URLFinder) (string, error) { 23 | res, err := http.Get(url) 24 | if err != nil { 25 | return "", err 26 | } 27 | defer res.Body.Close() 28 | 29 | if res.StatusCode != 200 { 30 | return "", fmt.Errorf("status code error: %d %s", res.StatusCode, res.Status) 31 | } 32 | 33 | body, err := io.ReadAll(res.Body) 34 | if err != nil { 35 | return "", fmt.Errorf("error reading JSON response: %v", err) 36 | } 37 | 38 | return finder.FindURL(body) 39 | } 40 | 41 | func GetJson(url string) (body []byte, err error) { 42 | res, err := http.Get(url) 43 | if err != nil { 44 | return []byte{}, err 45 | } 46 | defer res.Body.Close() 47 | 48 | if res.StatusCode != 200 { 49 | return []byte{}, fmt.Errorf("status code error: %d %s", res.StatusCode, res.Status) 50 | } 51 | 52 | body, err = io.ReadAll(res.Body) 53 | if err != nil { 54 | return []byte{}, fmt.Errorf("error reading response: %v", err) 55 | } 56 | return body, nil 57 | } 58 | 59 | func (m *UpdateManager) InsertPrefixes(prefixes []db.PrefixInfo) error { 60 | err := m.PrefixManager.AddPrefixBatch(prefixes) 61 | if err != nil { 62 | return fmt.Errorf("error inserting data %v", err) 63 | } 64 | slog.Info("successfully inserted prefixes", "count", len(prefixes)) 65 | return nil 66 | } 67 | 68 | func (m *UpdateManager) UpdateAllSources() { 69 | err := m.PrefixManager.ClearAllData() 70 | if err != nil { 71 | log.Fatalf("failed to clear existing data: %v", err) 72 | } 73 | 74 | slog.Info("Updating prefixes: GitHub") 75 | err = m.UpdateGithubPrefixes("https://api.github.com/meta") 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | 80 | slog.Info("Updating prefixes: Azure public") 81 | err = m.UpdateAzurePrefixes("https://www.microsoft.com/en-us/download/details.aspx?id=56519") 82 | if err != nil { 83 | log.Fatal(err) 84 | } 85 | slog.Info("Updating prefixes: Azure US government") 86 | err = m.UpdateAzurePrefixes("https://www.microsoft.com/en-us/download/details.aspx?id=57063") 87 | if err != nil { 88 | log.Fatal(err) 89 | } 90 | slog.Info("Updating prefixes: Azure China") 91 | err = m.UpdateAzurePrefixes("https://www.microsoft.com/en-us/download/details.aspx?id=57062") 92 | if err != nil { 93 | log.Fatal(err) 94 | } 95 | slog.Info("Updating prefixes: Azure Germany") 96 | err = m.UpdateAzurePrefixes("https://www.microsoft.com/en-au/download/details.aspx?id=57064") 97 | if err != nil { 98 | log.Fatal(err) 99 | } 100 | 101 | slog.Info("Updating prefixes: AWS") 102 | err = m.UpdateAwsPrefixes("https://ip-ranges.amazonaws.com/ip-ranges.json") 103 | if err != nil { 104 | log.Fatal(err) 105 | } 106 | 107 | slog.Info("Updating prefixes: GCP") 108 | err = m.UpdateGooglePrefixes("https://www.gstatic.com/ipranges/cloud.json", "GCP") 109 | if err != nil { 110 | log.Fatal(err) 111 | } 112 | 113 | slog.Info("Updating prefixes: Google") 114 | err = m.UpdateGooglePrefixes("https://www.gstatic.com/ipranges/goog.json", "Google") 115 | if err != nil { 116 | log.Fatal(err) 117 | } 118 | 119 | slog.Info("Updating prefixes: Oracle") 120 | err = m.UpdateOraclePrefixes("https://docs.oracle.com/en-us/iaas/tools/public_ip_ranges.json") 121 | if err != nil { 122 | log.Fatal(err) 123 | } 124 | 125 | geofeeds := []struct { 126 | url string 127 | name string 128 | }{ 129 | {name: "Digial Ocean", url: "https://digitalocean.com/geo/google.csv"}, 130 | {name: "CloudFlare", url: "https://www.cloudflare.com/ips-v4"}, 131 | {name: "CloudFlare", url: "https://www.cloudflare.com/ips-v6"}, 132 | } 133 | for _, g := range geofeeds { 134 | slog.Info("Updating prefixes:", "geofeed", g.name) 135 | err = m.UpdateGeoFeedPrefixes(g.url, g.name) 136 | if err != nil { 137 | log.Fatal(err) 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /pkg/update/main_test.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | 9 | "github.com/mchaffe/cloudprefixes/pkg/db" 10 | ) 11 | 12 | type MockMicrosoftURLFinder struct{} 13 | 14 | func (m *MockMicrosoftURLFinder) GetJsonUrl(url string) (string, error) { 15 | if url == "invalid" { 16 | return "", fmt.Errorf("unable to match URL in html response") 17 | } 18 | return strings.TrimSuffix(url, "html") + "json", nil 19 | } 20 | 21 | func TestUpdateManager_InsertPrefixes(t *testing.T) { 22 | // Initialize an in-memory SQLite database for testing 23 | dbConn, err := sql.Open("sqlite", ":memory:") 24 | if err != nil { 25 | t.Fatalf("Failed to open in-memory SQLite database: %v", err) 26 | } 27 | defer dbConn.Close() 28 | 29 | // Create a PrefixManager instance with the test database 30 | prefixManager, err := db.NewPrefixManager(":memory:") // Use in-memory DB for tests 31 | if err != nil { 32 | t.Fatalf("Failed to initialize PrefixManager: %v", err) 33 | } 34 | defer prefixManager.Close() 35 | 36 | // Initialize UpdateManager with the PrefixManager 37 | updateManager := NewUpdateManager(prefixManager) 38 | 39 | tests := []struct { 40 | name string 41 | prefixes []db.PrefixInfo 42 | wantErr bool 43 | }{ 44 | { 45 | name: "Insert valid prefixes", 46 | prefixes: []db.PrefixInfo{ 47 | { 48 | Prefix: "192.168.1.0/24", 49 | Platform: "AWS", 50 | Region: stringPointer("us-east-1"), 51 | }, 52 | { 53 | Prefix: "2001:db8::/32", 54 | Platform: "GCP", 55 | Region: stringPointer("global"), 56 | }, 57 | }, 58 | wantErr: false, 59 | }, 60 | { 61 | name: "Insert empty prefixes", 62 | prefixes: []db.PrefixInfo{}, 63 | wantErr: false, 64 | }, 65 | } 66 | 67 | for _, tt := range tests { 68 | t.Run(tt.name, func(t *testing.T) { 69 | err := updateManager.InsertPrefixes(tt.prefixes) 70 | if (err != nil) != tt.wantErr { 71 | t.Errorf("UpdateManager.InsertPrefixes() error = %v, wantErr %v", err, tt.wantErr) 72 | } 73 | }) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pkg/update/oracle.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/mchaffe/cloudprefixes/pkg/db" 7 | ) 8 | 9 | type OracleResponse struct { 10 | LastUpdatedTimestamp string `json:"last_updated_timestamp"` 11 | Regions []struct { 12 | Region *string `json:"region"` 13 | Cidrs []struct { 14 | Cidr string `json:"cidr"` 15 | Tags []string `json:"tags"` 16 | } `json:"cidrs"` 17 | } `json:"regions"` 18 | } 19 | 20 | func (m *UpdateManager) UpdateOraclePrefixes(url string) error { 21 | body, err := GetJson(url) 22 | if err != nil { 23 | return err 24 | } 25 | 26 | var j OracleResponse 27 | err = json.Unmarshal(body, &j) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | var prefixes []db.PrefixInfo 33 | for _, r := range j.Regions { 34 | for _, c := range r.Cidrs { 35 | for _, t := range c.Tags { 36 | prefixes = append(prefixes, db.PrefixInfo{ 37 | Platform: "Oracle", 38 | Region: r.Region, 39 | Prefix: c.Cidr, 40 | Service: &t, 41 | }) 42 | } 43 | } 44 | } 45 | 46 | return m.InsertPrefixes(prefixes) 47 | } 48 | -------------------------------------------------------------------------------- /pkg/update/oracle_test.go: -------------------------------------------------------------------------------- 1 | package update 2 | 3 | import "testing" 4 | 5 | func TestUpdateManager_UpdateOraclePrefixes(t *testing.T) { 6 | manager, ts, cleanup := SetupUpdateManager() 7 | defer cleanup() 8 | 9 | tests := []struct { 10 | name string 11 | m *UpdateManager 12 | url string 13 | wantErr bool 14 | }{ 15 | {"working", manager, ts.URL() + "/oracle_response.json", false}, 16 | } 17 | for _, tt := range tests { 18 | t.Run(tt.name, func(t *testing.T) { 19 | if err := tt.m.UpdateOraclePrefixes(tt.url); (err != nil) != tt.wantErr { 20 | t.Errorf("UpdateManager.UpdateOraclePrefixes() error = %v, wantErr %v", err, tt.wantErr) 21 | } 22 | found, prefixes, err := manager.PrefixManager.ContainsIP("134.70.8.1") 23 | if err != nil { 24 | t.Fatalf("failed to query prefixes: %v", err) 25 | } 26 | 27 | if !found && len(prefixes) != 2 { 28 | t.Errorf("UpdateManager.UpdateAzurePrefixes() len = %d, wanted 2", len(prefixes)) 29 | } 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pkg/update/testdata/cloudflare_response.txt: -------------------------------------------------------------------------------- 1 | 173.245.48.0/20 2 | 103.21.244.0/22 3 | 103.22.200.0/22 4 | 103.31.4.0/22 5 | 141.101.64.0/18 6 | 108.162.192.0/18 7 | 190.93.240.0/20 8 | 188.114.96.0/20 9 | 197.234.240.0/22 10 | 198.41.128.0/17 11 | 162.158.0.0/15 12 | 104.16.0.0/13 13 | 104.24.0.0/14 14 | 172.64.0.0/13 15 | 131.0.72.0/22 -------------------------------------------------------------------------------- /pkg/update/testdata/digitalocean_response.csv: -------------------------------------------------------------------------------- 1 | 5.101.96.0/21,NL,NL-NH,Amsterdam,1098 XH 2 | 5.101.104.0/22,NL,NL-NH,Amsterdam,1098 XH 3 | 24.144.64.0/22,US,US-NJ,North Bergen,07047 4 | 24.144.68.0/22,US,US-CA,Santa Clara,95054 5 | 24.144.76.0/22,NL,NL-NH,Amsterdam,1098 XH 6 | 24.144.80.0/20,US,US-CA,Santa Clara,95054 7 | 24.144.96.0/19,US,US-NJ,North Bergen,07047 8 | 24.199.64.0/22,US,US-NJ,North Bergen,07047 9 | 24.199.68.0/22,US,US-CA,Santa Clara,95054 10 | 24.199.72.0/21,US,US-CA,Santa Clara,95054 11 | 24.199.80.0/20,US,US-NJ,North Bergen,07047 12 | 24.199.96.0/20,US,US-CA,Santa Clara,95054 13 | 24.199.112.0/20,US,US-CA,Santa Clara,95054 14 | 37.139.0.0/19,NL,NL-NH,Amsterdam,1098 XH 15 | 45.55.0.0/19,US,US-SF,San Francisco,94124 16 | 45.55.32.0/19,US,US-NJ,Clifton,07014 17 | 45.55.64.0/19,US,US-NJ,Clifton,07014 18 | 45.55.96.0/22,US,US-NJ,Clifton,07014 19 | 45.55.100.0/22,US,US-NY,New York,10011 20 | 45.55.104.0/22,US,US-NJ,North Bergen,07047 21 | 45.55.108.0/22,US,US-SF,San Francisco,94124 22 | 45.55.112.0/22,US,US-SF,San Francisco,94124 23 | 45.55.116.0/22,US,US-NY,New York,10011 24 | 45.55.120.0/22,US,US-NJ,Clifton,07014 25 | 45.55.124.0/22,US,US-NJ,Clifton,07014 26 | 45.55.128.0/18,US,US-NJ,Clifton,07014 27 | 45.55.192.0/18,US,US-NJ,Clifton,07014 28 | 46.101.0.0/18,GB,GB-SLG,London,SL1 4AX 29 | 46.101.64.0/22,GB,GB-SLG,London,SL1 4AX 30 | 46.101.68.0/22,DE,DE-HE,Frankfurt,60341 31 | 46.101.72.0/21,GB,GB-SLG,London,SL1 4AX 32 | 46.101.80.0/20,GB,GB-SLG,London,SL1 4AX 33 | 46.101.96.0/19,DE,DE-HE,Frankfurt,60341 34 | 46.101.128.0/17,DE,DE-HE,Frankfurt,60341 35 | 64.23.128.0/20,US,US-CA,Santa Clara,95054 36 | 64.23.144.0/20,US,US-CA,Santa Clara,95054 37 | 64.23.160.0/20,US,US-CA,Santa Clara,95054 38 | 64.23.176.0/20,US,US-CA,Santa Clara,95054 39 | 64.23.192.0/19,US,US-CA,Santa Clara,95054 40 | 64.23.224.0/20,US,US-CA,Santa Clara,95054 41 | 64.23.240.0/20,US,US-CA,Santa Clara,95054 42 | 64.225.0.0/20,US,US-NJ,Clifton,07014 43 | 64.225.16.0/20,US,US-NJ,Clifton,07014 44 | 64.225.32.0/20,US,US-CA,Santa Clara,95051 45 | 64.225.48.0/20,US,US-NJ,Clifton,07014 46 | 64.225.64.0/20,NL,NL-NH,Amsterdam,1098 XH 47 | 64.225.80.0/22,NL,NL-NH,Amsterdam,1098 XH 48 | 64.225.84.0/22,IN,IN-KA,Bangalore,560100 49 | 64.225.88.0/22,US,US-CA,Santa Clara,95054 50 | 64.225.92.0/22,DE,DE-HE,Frankfurt,60341 51 | 64.225.96.0/20,DE,DE-HE,Frankfurt,60341 52 | 64.225.112.0/20,US,US-CA,Santa Clara,95051 53 | 64.226.64.0/20,DE,DE-HE,Frankfurt,60341 54 | 64.226.80.0/20,DE,DE-HE,Frankfurt,60341 55 | 64.226.96.0/20,DE,DE-HE,Frankfurt,60341 56 | 64.226.112.0/20,DE,DE-HE,Frankfurt,60341 57 | 64.227.0.0/20,US,US-NJ,North Bergen,07047 58 | 64.227.16.0/20,US,US-NJ,North Bergen,07047 59 | 64.227.32.0/20,GB,GB-SLG,London,SL1 4AX 60 | 64.227.48.0/20,US,US-CA,Santa Clara,95051 61 | 64.227.64.0/20,NL,NL-NH,Amsterdam,1098 XH 62 | 64.227.80.0/20,US,US-CA,Santa Clara,95051 63 | 64.227.96.0/20,US,US-CA,Santa Clara,95054 64 | 64.227.112.0/20,DE,DE-HE,Frankfurt,60341 65 | 64.227.128.0/19,IN,IN-KA,Bangalore,560100 66 | 64.227.160.0/20,IN,IN-KA,Bangalore,560100 67 | 64.227.176.0/20,IN,IN-KA,Bangalore,560100 68 | 67.205.128.0/20,US,US-NJ,North Bergen,07047 69 | 67.205.144.0/20,US,US-NJ,North Bergen,07047 70 | 67.205.160.0/20,US,US-NJ,North Bergen,07047 71 | 67.205.176.0/20,US,US-NJ,North Bergen,07047 72 | 67.207.68.0/22,GB,GB-SLG,London,SL1 4AX 73 | 67.207.72.0/22,DE,DE-HE,Frankfurt,60341 74 | 67.207.76.0/22,DE,DE-HE,Frankfurt,60341 75 | 67.207.80.0/20,US,US-NJ,North Bergen,07047 76 | 68.183.0.0/20,NL,NL-NH,Amsterdam,1098 XH 77 | 68.183.16.0/20,US,US-NJ,North Bergen,07047 78 | 68.183.32.0/20,GB,GB-SLG,London,SL1 4AX 79 | 68.183.48.0/20,US,US-NJ,Clifton,07014 80 | 68.183.64.0/20,DE,DE-HE,Frankfurt,60341 81 | 68.183.80.0/20,IN,IN-KA,Bangalore,560100 82 | 68.183.96.0/20,US,US-NJ,North Bergen,07047 83 | 68.183.112.0/20,US,US-NJ,North Bergen,07047 84 | 68.183.128.0/20,US,US-NJ,North Bergen,07047 85 | 68.183.144.0/20,US,US-NJ,Clifton,07014 86 | 68.183.160.0/20,US,US-CA,Santa Clara,95051 87 | 68.183.176.0/20,SG,SG-05,Singapore,627753 88 | 68.183.192.0/20,CA,CA-ON,Toronto,M5A 0B2 89 | 68.183.208.0/20,DE,DE-HE,Frankfurt,60341 90 | 68.183.224.0/20,SG,SG-05,Singapore,627753 91 | 68.183.240.0/22,DE,DE-HE,Frankfurt,60341 92 | 68.183.244.0/22,IN,IN-KA,Bangalore,560100 93 | 68.183.248.0/22,US,US-CA,Santa Clara,95051 94 | 68.183.252.0/22,GB,GB-SLG,London,SL1 4AX 95 | 69.55.49.0/24,US,US-NJ,North Bergen,07047 96 | 69.55.54.0/24,US,US-NJ,North Bergen,07047 97 | 69.55.55.0/24,US,US-NJ,North Bergen,07047 98 | 69.55.59.64/26,US,US-NJ,North Bergen,07047 99 | 69.55.59.128/26,US,US-NJ,North Bergen,07047 100 | 69.55.59.192/27,US,US-NJ,North Bergen,07047 101 | 69.55.60.96/27,US,US-NJ,North Bergen,07047 102 | 69.55.60.128/26,US,US-NJ,North Bergen,07047 103 | 69.55.61.64/26,US,US-NJ,North Bergen,07047 104 | 69.55.62.0/26,US,US-NJ,North Bergen,07047 105 | 80.240.128.0/20,NL,NL-NH,Amsterdam,1098 XH 106 | 82.196.0.0/20,NL,NL-NH,Amsterdam,1098 XH 107 | 95.85.1.0/24,NL,NL-NH,Amsterdam,1098 XH 108 | 95.85.2.0/24,NL,NL-NH,Amsterdam,1098 XH 109 | 95.85.3.0/24,NL,NL-NH,Amsterdam,1098 XH 110 | 95.85.4.0/24,NL,NL-NH,Amsterdam,1098 XH 111 | 95.85.5.0/24,NL,NL-NH,Amsterdam,1098 XH 112 | 95.85.6.0/24,NL,NL-NH,Amsterdam,1098 XH 113 | 95.85.7.0/24,NL,NL-NH,Amsterdam,1098 XH 114 | 95.85.8.0/24,NL,NL-NH,Amsterdam,1098 XH 115 | 95.85.9.0/24,NL,NL-NH,Amsterdam,1098 XH 116 | 95.85.10.0/24,NL,NL-NH,Amsterdam,1098 XH 117 | 95.85.11.0/24,NL,NL-NH,Amsterdam,1098 XH 118 | 95.85.12.0/24,NL,NL-NH,Amsterdam,1098 XH 119 | 95.85.13.0/24,NL,NL-NH,Amsterdam,1098 XH 120 | 95.85.14.0/24,NL,NL-NH,Amsterdam,1098 XH 121 | 95.85.15.0/24,NL,NL-NH,Amsterdam,1098 XH 122 | 95.85.16.0/24,NL,NL-NH,Amsterdam,1098 XH 123 | 95.85.17.0/24,NL,NL-NH,Amsterdam,1098 XH 124 | 95.85.18.0/24,NL,NL-NH,Amsterdam,1098 XH 125 | 95.85.19.0/24,NL,NL-NH,Amsterdam,1098 XH 126 | 95.85.20.0/24,NL,NL-NH,Amsterdam,1098 XH 127 | 95.85.21.0/24,NL,NL-NH,Amsterdam,1098 XH 128 | 95.85.22.0/24,NL,NL-NH,Amsterdam,1098 XH 129 | 95.85.23.0/24,NL,NL-NH,Amsterdam,1098 XH 130 | 95.85.24.0/24,NL,NL-NH,Amsterdam,1098 XH 131 | 95.85.25.0/24,NL,NL-NH,Amsterdam,1098 XH 132 | 95.85.26.0/24,NL,NL-NH,Amsterdam,1098 XH 133 | 95.85.27.0/24,NL,NL-NH,Amsterdam,1098 XH 134 | 95.85.28.0/24,NL,NL-NH,Amsterdam,1098 XH 135 | 95.85.29.0/24,NL,NL-NH,Amsterdam,1098 XH 136 | 95.85.30.0/24,NL,NL-NH,Amsterdam,1098 XH 137 | 95.85.31.0/24,NL,NL-NH,Amsterdam,1098 XH 138 | 95.85.32.0/24,NL,NL-NH,Amsterdam,1098 XH 139 | 95.85.33.0/24,NL,NL-NH,Amsterdam,1098 XH 140 | 95.85.34.0/24,NL,NL-NH,Amsterdam,1098 XH 141 | 95.85.35.0/24,NL,NL-NH,Amsterdam,1098 XH 142 | 95.85.36.0/24,NL,NL-NH,Amsterdam,1098 XH 143 | 95.85.37.0/24,NL,NL-NH,Amsterdam,1098 XH 144 | 95.85.38.0/24,NL,NL-NH,Amsterdam,1098 XH 145 | 95.85.39.0/24,NL,NL-NH,Amsterdam,1098 XH 146 | 95.85.40.0/24,NL,NL-NH,Amsterdam,1098 XH 147 | 95.85.41.0/24,NL,NL-NH,Amsterdam,1098 XH 148 | 95.85.42.0/24,NL,NL-NH,Amsterdam,1098 XH 149 | 95.85.43.0/24,NL,NL-NH,Amsterdam,1098 XH 150 | 95.85.44.0/24,NL,NL-NH,Amsterdam,1098 XH 151 | 95.85.45.0/24,NL,NL-NH,Amsterdam,1098 XH 152 | 95.85.46.0/24,NL,NL-NH,Amsterdam,1098 XH 153 | 95.85.47.0/24,NL,NL-NH,Amsterdam,1098 XH 154 | 95.85.48.0/24,NL,NL-NH,Amsterdam,1098 XH 155 | 95.85.49.0/24,NL,NL-NH,Amsterdam,1098 XH 156 | 95.85.50.0/24,NL,NL-NH,Amsterdam,1098 XH 157 | 95.85.51.0/24,NL,NL-NH,Amsterdam,1098 XH 158 | 95.85.52.0/24,NL,NL-NH,Amsterdam,1098 XH 159 | 95.85.53.0/24,NL,NL-NH,Amsterdam,1098 XH 160 | 95.85.54.0/24,NL,NL-NH,Amsterdam,1098 XH 161 | 95.85.55.0/24,NL,NL-NH,Amsterdam,1098 XH 162 | 95.85.56.0/24,NL,NL-NH,Amsterdam,1098 XH 163 | 95.85.57.0/24,NL,NL-NH,Amsterdam,1098 XH 164 | 95.85.58.0/24,NL,NL-NH,Amsterdam,1098 XH 165 | 95.85.59.0/24,NL,NL-NH,Amsterdam,1098 XH 166 | 95.85.60.0/24,NL,NL-NH,Amsterdam,1098 XH 167 | 95.85.61.0/24,NL,NL-NH,Amsterdam,1098 XH 168 | 95.85.62.0/24,NL,NL-NH,Amsterdam,1098 XH 169 | 95.85.63.0/24,NL,NL-NH,Amsterdam,1098 XH 170 | 103.253.145.0/24,SG,SG-05,Singapore,627753 171 | 103.253.146.0/24,SG,SG-05,Singapore,627753 172 | 103.253.147.0/24,SG,SG-05,Singapore,627753 173 | 104.131.0.0/18,US,US-NJ,Clifton,07014 174 | 104.131.64.0/18,US,US-NJ,Clifton,07014 175 | 104.131.128.0/20,US,US-SF,San Francisco,94124 176 | 104.131.144.0/20,US,US-SF,San Francisco,94124 177 | 104.131.160.0/20,US,US-NJ,Clifton,07014 178 | 104.131.176.0/20,US,US-NJ,Clifton,07014 179 | 104.131.192.0/19,US,US-NY,New York,10011 180 | 104.131.224.0/19,US,US-NY,New York,10011 181 | 104.236.0.0/18,US,US-NJ,Clifton,07014 182 | 104.236.64.0/18,US,US-NJ,Clifton,07014 183 | 104.236.128.0/18,US,US-SF,San Francisco,94124 184 | 104.236.192.0/18,US,US-NJ,Clifton,07014 185 | 104.248.0.0/20,US,US-NJ,Clifton,07014 186 | 104.248.16.0/20,DE,DE-HE,Frankfurt,60341 187 | 104.248.32.0/20,DE,DE-HE,Frankfurt,60341 188 | 104.248.48.0/20,US,US-NJ,North Bergen,07047 189 | 104.248.64.0/20,US,US-CA,Santa Clara,95051 190 | 104.248.80.0/20,NL,NL-NH,Amsterdam,1098 XH 191 | 104.248.96.0/22,SG,SG-05,Singapore,627753 192 | 104.248.100.0/22,DE,DE-HE,Frankfurt,60341 193 | 104.248.104.0/22,CA,CA-ON,Toronto,M5A 0B2 194 | 104.248.108.0/22,US,US-NJ,North Bergen,07047 195 | 104.248.112.0/20,US,US-NJ,North Bergen,07047 196 | 104.248.128.0/20,DE,DE-HE,Frankfurt,60341 197 | 104.248.144.0/20,SG,SG-05,Singapore,627753 198 | 104.248.160.0/20,GB,GB-SLG,London,SL1 4AX 199 | 104.248.176.0/20,US,US-CA,Santa Clara,95051 200 | 104.248.192.0/20,NL,NL-NH,Amsterdam,1098 XH 201 | 104.248.208.0/20,US,US-CA,Santa Clara,95051 202 | 104.248.224.0/20,US,US-NJ,North Bergen,07047 203 | 104.248.240.0/20,DE,DE-HE,Frankfurt,60341 204 | 107.170.0.0/17,US,US-NY,New York,10011 205 | 107.170.128.0/19,US,US-NY,New York,10011 206 | 107.170.160.0/19,US,US-NY,New York,10011 207 | 107.170.192.0/20,US,US-SF,San Francisco,94124 208 | 107.170.208.0/20,US,US-SF,San Francisco,94124 209 | 107.170.224.0/24,US,US-SF,San Francisco,94124 210 | 107.170.225.0/24,US,US-SF,San Francisco,94124 211 | 107.170.226.0/24,US,US-SF,San Francisco,94124 212 | 107.170.227.0/24,US,US-SF,San Francisco,94124 213 | 107.170.228.0/24,US,US-SF,San Francisco,94124 214 | 107.170.229.0/24,US,US-SF,San Francisco,94124 215 | 107.170.230.0/24,US,US-SF,San Francisco,94124 216 | 107.170.231.0/24,US,US-SF,San Francisco,94124 217 | 107.170.232.0/24,US,US-SF,San Francisco,94124 218 | 107.170.233.0/24,US,US-SF,San Francisco,94124 219 | 107.170.234.0/24,US,US-SF,San Francisco,94124 220 | 107.170.235.0/24,US,US-SF,San Francisco,94124 221 | 107.170.236.0/24,US,US-SF,San Francisco,94124 222 | 107.170.237.0/24,US,US-SF,San Francisco,94124 223 | 107.170.238.0/24,US,US-SF,San Francisco,94124 224 | 107.170.239.0/24,US,US-SF,San Francisco,94124 225 | 107.170.240.0/24,US,US-SF,San Francisco,94124 226 | 107.170.241.0/24,US,US-SF,San Francisco,94124 227 | 107.170.242.0/24,US,US-SF,San Francisco,94124 228 | 107.170.243.0/24,US,US-SF,San Francisco,94124 229 | 107.170.244.0/24,US,US-SF,San Francisco,94124 230 | 107.170.245.0/24,US,US-SF,San Francisco,94124 231 | 107.170.246.0/24,US,US-SF,San Francisco,94124 232 | 107.170.247.0/24,US,US-SF,San Francisco,94124 233 | 107.170.248.0/24,US,US-SF,San Francisco,94124 234 | 107.170.249.0/24,US,US-SF,San Francisco,94124 235 | 107.170.250.0/24,US,US-SF,San Francisco,94124 236 | 107.170.251.0/24,US,US-SF,San Francisco,94124 237 | 107.170.252.0/24,US,US-SF,San Francisco,94124 238 | 107.170.253.0/24,US,US-SF,San Francisco,94124 239 | 107.170.254.0/24,US,US-SF,San Francisco,94124 240 | 107.170.255.0/24,US,US-SF,San Francisco,94124 241 | 128.199.0.0/20,US,US-CA,Santa Clara,95054 242 | 128.199.16.0/20,IN,IN-KA,Bangalore,560100 243 | 128.199.32.0/19,NL,NL-NH,Amsterdam,1098 XH 244 | 128.199.64.0/18,SG,SG-05,Singapore,627753 245 | 128.199.128.0/18,SG,SG-05,Singapore,627753 246 | 128.199.192.0/18,SG,SG-05,Singapore,627753 247 | 134.122.0.0/20,US,US-NJ,Clifton,07014 248 | 134.122.16.0/20,US,US-NJ,North Bergen,07047 249 | 134.122.32.0/20,CA,CA-ON,Toronto,M5A 0B2 250 | 134.122.48.0/20,NL,NL-NH,Amsterdam,1098 XH 251 | 134.122.64.0/20,DE,DE-HE,Frankfurt,60341 252 | 134.122.80.0/20,DE,DE-HE,Frankfurt,60341 253 | 134.122.96.0/20,GB,GB-SLG,London,SL1 4AX 254 | 134.122.112.0/20,US,US-NJ,North Bergen,07047 255 | 134.209.0.0/20,US,US-CA,Santa Clara,95051 256 | 134.209.16.0/20,GB,GB-SLG,London,SL1 4AX 257 | 134.209.32.0/20,US,US-NJ,Clifton,07014 258 | 134.209.48.0/20,US,US-CA,Santa Clara,95051 259 | 134.209.64.0/20,US,US-NJ,North Bergen,07047 260 | 134.209.80.0/20,NL,NL-NH,Amsterdam,1098 XH 261 | 134.209.96.0/20,SG,SG-05,Singapore,627753 262 | 134.209.112.0/20,US,US-NJ,North Bergen,07047 263 | 134.209.128.0/22,US,US-NJ,North Bergen,07047 264 | 134.209.132.0/22,NL,NL-NH,Amsterdam,1098 XH 265 | 134.209.136.0/22,NL,NL-NH,Amsterdam,1098 XH 266 | 134.209.140.0/22,US,US-CA,Santa Clara,95051 267 | 134.209.144.0/20,IN,IN-KA,Bangalore,560100 268 | 134.209.160.0/20,US,US-NJ,Clifton,07014 269 | 134.209.176.0/20,GB,GB-SLG,London,SL1 4AX 270 | 134.209.192.0/20,NL,NL-NH,Amsterdam,1098 XH 271 | 134.209.208.0/20,US,US-NJ,North Bergen,07047 272 | 134.209.224.0/20,DE,DE-HE,Frankfurt,60341 273 | 134.209.240.0/20,DE,DE-HE,Frankfurt,60341 274 | 137.184.0.0/20,US,US-CA,Santa Clara,95054 275 | 137.184.16.0/20,US,US-NJ,North Bergen,07047 276 | 137.184.32.0/20,US,US-CA,Santa Clara,95054 277 | 137.184.48.0/20,US,US-NJ,North Bergen,07047 278 | 137.184.64.0/20,US,US-NJ,North Bergen,07047 279 | 137.184.80.0/20,US,US-CA,Santa Clara,95054 280 | 137.184.96.0/20,US,US-NJ,North Bergen,07047 281 | 137.184.112.0/20,US,US-CA,Santa Clara,95054 282 | 137.184.128.0/20,US,US-NJ,North Bergen,07047 283 | 137.184.144.0/20,US,US-NJ,North Bergen,07047 284 | 137.184.160.0/20,CA,CA-ON,Toronto,M5A 0B2 285 | 137.184.176.0/20,US,US-CA,Santa Clara,95054 286 | 137.184.192.0/20,US,US-NJ,North Bergen,07047 287 | 137.184.208.0/20,US,US-NJ,North Bergen,07047 288 | 137.184.224.0/20,US,US-CA,Santa Clara,95054 289 | 137.184.240.0/22,US,US-NJ,North Bergen,07047 290 | 137.184.244.0/22,US,US-CA,Santa Clara,95054 291 | 137.184.248.0/22,SG,SG-05,Singapore,627753 292 | 137.184.254.0/24,US,US-NY,New York,10011 293 | 137.184.255.0/24,US,US-SF,San Francisco,94124 294 | 138.68.0.0/20,US,US-CA,Santa Clara,95051 295 | 138.68.16.0/20,US,US-CA,Santa Clara,95051 296 | 138.68.36.0/22,US,US-CA,Santa Clara,95051 297 | 138.68.40.0/21,US,US-CA,Santa Clara,95051 298 | 138.68.48.0/20,US,US-CA,Santa Clara,95051 299 | 138.68.64.0/20,DE,DE-HE,Frankfurt,60341 300 | 138.68.80.0/20,DE,DE-HE,Frankfurt,60341 301 | 138.68.96.0/20,DE,DE-HE,Frankfurt,60341 302 | 138.68.112.0/22,DE,DE-HE,Frankfurt,60341 303 | 138.68.116.0/22,GB,GB-SLG,London,SL1 4AX 304 | 138.68.120.0/23,NL,NL-NH,Amsterdam,1098 XH 305 | 138.68.122.0/23,NL,NL-NH,Amsterdam,1098 XH 306 | 138.68.124.0/22,DE,DE-HE,Frankfurt,60341 307 | 138.68.128.0/20,GB,GB-SLG,London,SL1 4AX 308 | 138.68.144.0/20,GB,GB-SLG,London,SL1 4AX 309 | 138.68.160.0/20,GB,GB-SLG,London,SL1 4AX 310 | 138.68.176.0/20,GB,GB-SLG,London,SL1 4AX 311 | 138.68.192.0/22,US,US-SF,San Francisco,94124 312 | 138.68.196.0/22,US,US-SF,San Francisco,94124 313 | 138.68.200.0/22,US,US-SF,San Francisco,94124 314 | 138.68.204.0/22,NL,NL-NH,Amsterdam,1098 XH 315 | 138.68.208.0/20,US,US-SF,San Francisco,94124 316 | 138.68.224.0/20,US,US-CA,Santa Clara,95051 317 | 138.68.240.0/20,US,US-CA,Santa Clara,95051 318 | 138.197.0.0/20,US,US-NJ,Clifton,07014 319 | 138.197.16.0/20,US,US-NJ,Clifton,07014 320 | 138.197.32.0/20,US,US-NJ,Clifton,07014 321 | 138.197.48.0/22,US,US-NJ,Clifton,07014 322 | 138.197.52.0/22,US,US-NJ,Clifton,07014 323 | 138.197.56.0/22,US,US-NJ,Clifton,07014 324 | 138.197.60.0/22,US,US-NJ,Clifton,07014 325 | 138.197.64.0/20,US,US-NJ,Clifton,07014 326 | 138.197.80.0/20,US,US-NJ,Clifton,07014 327 | 138.197.96.0/20,US,US-NJ,Clifton,07014 328 | 138.197.112.0/20,US,US-NJ,Clifton,07014 329 | 138.197.128.0/20,CA,CA-ON,Toronto,M5A 0B2 330 | 138.197.144.0/20,CA,CA-ON,Toronto,M5A 0B2 331 | 138.197.160.0/20,CA,CA-ON,Toronto,M5A 0B2 332 | 138.197.176.0/20,DE,DE-HE,Frankfurt,60341 333 | 138.197.192.0/20,US,US-CA,Santa Clara,95051 334 | 138.197.208.0/20,US,US-CA,Santa Clara,95051 335 | 138.197.224.0/22,US,US-NJ,North Bergen,07047 336 | 138.197.228.0/22,US,US-NJ,North Bergen,07047 337 | 138.197.232.0/22,US,US-CA,Santa Clara,95051 338 | 138.197.236.0/22,US,US-CA,Santa Clara,95051 339 | 138.197.240.0/22,US,US-NY,New York,10011 340 | 138.197.252.0/22,US,US-NY,New York,10011 341 | 139.59.0.0/20,IN,IN-KA,Bangalore,560100 342 | 139.59.16.0/20,IN,IN-KA,Bangalore,560100 343 | 139.59.32.0/20,IN,IN-KA,Bangalore,560100 344 | 139.59.48.0/22,IN,IN-KA,Bangalore,560100 345 | 139.59.52.0/22,IN,IN-KA,Bangalore,560100 346 | 139.59.56.0/21,IN,IN-KA,Bangalore,560100 347 | 139.59.64.0/20,IN,IN-KA,Bangalore,560100 348 | 139.59.80.0/20,IN,IN-KA,Bangalore,560100 349 | 139.59.96.0/20,SG,SG-05,Singapore,627753 350 | 139.59.112.0/20,SG,SG-05,Singapore,627753 351 | 139.59.128.0/19,DE,DE-HE,Frankfurt,60341 352 | 139.59.160.0/20,GB,GB-SLG,London,SL1 4AX 353 | 139.59.176.0/20,GB,GB-SLG,London,SL1 4AX 354 | 139.59.192.0/22,SG,SG-05,Singapore,627753 355 | 139.59.196.0/22,GB,GB-SLG,London,SL1 4AX 356 | 139.59.200.0/22,GB,GB-SLG,London,SL1 4AX 357 | 139.59.204.0/22,DE,DE-HE,Frankfurt,60341 358 | 139.59.208.0/21,DE,DE-HE,Frankfurt,60341 359 | 139.59.216.0/22,SG,SG-05,Singapore,627753 360 | 139.59.220.0/22,SG,SG-05,Singapore,627753 361 | 139.59.224.0/20,SG,SG-05,Singapore,627753 362 | 139.59.240.0/20,SG,SG-05,Singapore,627753 363 | 141.0.169.0/24,NL,NL-NH,Amsterdam,1098 XH 364 | 141.0.170.0/24,NL,NL-NH,Amsterdam,1098 XH 365 | 142.93.0.0/20,US,US-NJ,North Bergen,07047 366 | 142.93.16.0/20,US,US-CA,Santa Clara,95051 367 | 142.93.32.0/20,GB,GB-SLG,London,SL1 4AX 368 | 142.93.48.0/20,US,US-NJ,North Bergen,07047 369 | 142.93.64.0/20,US,US-NJ,Clifton,07014 370 | 142.93.80.0/20,US,US-CA,Santa Clara,95051 371 | 142.93.96.0/20,DE,DE-HE,Frankfurt,60341 372 | 142.93.112.0/20,US,US-NJ,North Bergen,07047 373 | 142.93.128.0/20,NL,NL-NH,Amsterdam,1098 XH 374 | 142.93.144.0/20,CA,CA-ON,Toronto,M5A 0B2 375 | 142.93.160.0/20,DE,DE-HE,Frankfurt,60341 376 | 142.93.176.0/20,US,US-NJ,Clifton,07014 377 | 142.93.192.0/20,US,US-NJ,North Bergen,07047 378 | 142.93.208.0/20,IN,IN-KA,Bangalore,560100 379 | 142.93.224.0/20,NL,NL-NH,Amsterdam,1098 XH 380 | 142.93.240.0/20,US,US-NJ,North Bergen,07047 381 | 143.110.128.0/20,US,US-CA,Santa Clara,95051 382 | 143.110.144.0/20,US,US-CA,Santa Clara,95054 383 | 143.110.160.0/20,GB,GB-SLG,London,SL1 4AX 384 | 143.110.176.0/20,IN,IN-KA,Bangalore,560100 385 | 143.110.192.0/20,US,US-CA,Santa Clara,95051 386 | 143.110.208.0/20,CA,CA-ON,Toronto,M5A 0B2 387 | 143.110.224.0/20,US,US-CA,Santa Clara,95054 388 | 143.110.240.0/20,IN,IN-KA,Bangalore,560100 389 | 143.198.0.0/20,US,US-NJ,Clifton,07014 390 | 143.198.16.0/20,US,US-NJ,Clifton,07014 391 | 143.198.32.0/20,CA,CA-ON,Toronto,M5A 0B2 392 | 143.198.48.0/20,US,US-CA,Santa Clara,95054 393 | 143.198.64.0/20,US,US-CA,Santa Clara,95054 394 | 143.198.80.0/20,SG,SG-05,Singapore,627753 395 | 143.198.96.0/20,US,US-CA,Santa Clara,95054 396 | 143.198.112.0/20,US,US-NJ,North Bergen,07047 397 | 143.198.128.0/20,US,US-CA,Santa Clara,95054 398 | 143.198.144.0/20,US,US-CA,Santa Clara,95054 399 | 143.198.160.0/20,US,US-NJ,North Bergen,07047 400 | 143.198.176.0/20,US,US-NJ,North Bergen,07047 401 | 143.198.192.0/20,SG,SG-05,Singapore,627753 402 | 143.198.208.0/20,SG,SG-05,Singapore,627753 403 | 143.198.224.0/20,US,US-CA,Santa Clara,95054 404 | 143.198.240.0/22,GB,GB-SLG,London,SL1 4AX 405 | 143.198.244.0/22,US,US-CA,Santa Clara,95054 406 | 143.198.248.0/22,NL,NL-NH,Amsterdam,1098 XH 407 | 143.244.128.0/20,IN,IN-KA,Bangalore,560100 408 | 143.244.144.0/20,US,US-NJ,North Bergen,07047 409 | 143.244.160.0/20,US,US-NJ,North Bergen,07047 410 | 143.244.176.0/20,US,US-CA,Santa Clara,95054 411 | 143.244.196.0/22,NL,NL-NH,Amsterdam,1098 XH 412 | 143.244.200.0/22,US,US-NJ,North Bergen,07047 413 | 143.244.204.0/22,DE,DE-HE,Frankfurt,60341 414 | 143.244.208.0/22,US,US-CA,Santa Clara,95054 415 | 143.244.212.0/22,US,US-NJ,North Bergen,07047 416 | 143.244.218.0/24,NL,NL-NH,Amsterdam,1098 XH 417 | 143.244.220.0/22,US,US-NJ,Clifton,07014 418 | 144.126.192.0/20,GB,GB-SLG,London,SL1 4AX 419 | 144.126.208.0/20,US,US-CA,Santa Clara,95054 420 | 144.126.224.0/20,GB,GB-SLG,London,SL1 4AX 421 | 144.126.240.0/22,SG,SG-05,Singapore,627753 422 | 144.126.244.0/22,DE,DE-HE,Frankfurt,60341 423 | 144.126.248.0/22,US,US-NJ,Clifton,07014 424 | 144.126.252.0/22,IN,IN-KA,Bangalore,560100 425 | 146.185.128.0/19,NL,NL-NH,Amsterdam,1098 XH 426 | 146.185.160.0/20,NL,NL-NH,Amsterdam,1098 XH 427 | 146.185.176.0/21,NL,NL-NH,Amsterdam,1098 XH 428 | 146.185.184.0/21,NL,NL-NH,Amsterdam,1098 XH 429 | 146.190.0.0/22,US,US-CA,Santa Clara,95054 430 | 146.190.4.0/22,SG,SG-05,Singapore,627753 431 | 146.190.8.0/22,IN,IN-KA,Bangalore,560100 432 | 146.190.12.0/22,US,US-CA,Santa Clara,95054 433 | 146.190.16.0/20,NL,NL-NH,Amsterdam,1098 XH 434 | 146.190.32.0/19,US,US-CA,Santa Clara,95054 435 | 146.190.64.0/20,US,US-NJ,North Bergen,07047 436 | 146.190.80.0/20,SG,SG-05,Singapore,627753 437 | 146.190.96.0/20,SG,SG-05,Singapore,627753 438 | 146.190.112.0/20,US,US-CA,Santa Clara,95054 439 | 146.190.128.0/19,US,US-CA,Santa Clara,95054 440 | 146.190.160.0/20,US,US-CA,Santa Clara,95054 441 | 146.190.176.0/22,DE,DE-HE,Frankfurt,60341 442 | 146.190.184.0/22,US,US-NJ,North Bergen,07047 443 | 146.190.188.0/22,CA,CA-ON,Toronto,M5A 0B2 444 | 146.190.192.0/22,SG,SG-05,Singapore,627753 445 | 146.190.196.0/22,US,US-NJ,North Bergen,07047 446 | 146.190.200.0/22,SG,SG-05,Singapore,627753 447 | 146.190.204.0/22,DE,DE-HE,Frankfurt,60341 448 | 146.190.208.0/20,US,US-NJ,North Bergen,07047 449 | 146.190.224.0/20,NL,NL-NH,Amsterdam,1098 XH 450 | 146.190.240.0/20,CA,CA-ON,Toronto,M5A 0B2 451 | 147.182.128.0/20,US,US-NJ,North Bergen,07047 452 | 147.182.144.0/20,CA,CA-ON,Toronto,M5A 0B2 453 | 147.182.160.0/20,US,US-NJ,North Bergen,07047 454 | 147.182.176.0/20,US,US-NJ,North Bergen,07047 455 | 147.182.192.0/20,US,US-CA,Santa Clara,95054 456 | 147.182.208.0/20,US,US-NJ,North Bergen,07047 457 | 147.182.224.0/20,US,US-CA,Santa Clara,95054 458 | 147.182.240.0/20,US,US-CA,Santa Clara,95054 459 | 152.42.128.0/20,NL,NL-NH,Amsterdam,1098 XH 460 | 152.42.144.0/22,CA,CA-ON,Toronto,M5A 0B2 461 | 152.42.148.0/22,NL,NL-NH,Amsterdam,1098 XH 462 | 152.42.152.0/22,US,US-NJ,Clifton,07014 463 | 152.42.156.0/22,IN,IN-KA,Bangalore,560100 464 | 152.42.160.0/19,SG,SG-05,Singapore,627753 465 | 152.42.192.0/19,SG,SG-05,Singapore,627753 466 | 152.42.224.0/20,SG,SG-05,Singapore,627753 467 | 152.42.240.0/20,SG,SG-05,Singapore,627753 468 | 157.230.0.0/20,US,US-NJ,North Bergen,07047 469 | 157.230.16.0/20,DE,DE-HE,Frankfurt,60341 470 | 157.230.32.0/20,SG,SG-05,Singapore,627753 471 | 157.230.48.0/20,US,US-NJ,North Bergen,07047 472 | 157.230.64.0/22,US,US-NJ,North Bergen,07047 473 | 157.230.68.0/22,CA,CA-ON,Toronto,M5A 0B2 474 | 157.230.72.0/22,US,US-CA,Santa Clara,95051 475 | 157.230.76.0/22,DE,DE-HE,Frankfurt,60341 476 | 157.230.80.0/20,US,US-NJ,North Bergen,07047 477 | 157.230.96.0/20,DE,DE-HE,Frankfurt,60341 478 | 157.230.112.0/20,DE,DE-HE,Frankfurt,60341 479 | 157.230.128.0/20,US,US-CA,Santa Clara,95051 480 | 157.230.144.0/20,US,US-CA,Santa Clara,95051 481 | 157.230.160.0/20,US,US-CA,Santa Clara,95051 482 | 157.230.176.0/20,US,US-NJ,North Bergen,07047 483 | 157.230.192.0/22,SG,SG-05,Singapore,627753 484 | 157.230.196.0/22,US,US-CA,Santa Clara,95051 485 | 157.230.200.0/22,US,US-NJ,North Bergen,07047 486 | 157.230.204.0/22,US,US-CA,Santa Clara,95051 487 | 157.230.208.0/20,US,US-NJ,North Bergen,07047 488 | 157.230.224.0/20,US,US-NJ,North Bergen,07047 489 | 157.230.240.0/20,SG,SG-05,Singapore,627753 490 | 157.245.0.0/20,US,US-NJ,Clifton,07014 491 | 157.245.16.0/22,DE,DE-HE,Frankfurt,60341 492 | 157.245.20.0/22,DE,DE-HE,Frankfurt,60341 493 | 157.245.24.0/22,DE,DE-HE,Frankfurt,60341 494 | 157.245.28.0/22,GB,GB-SLG,London,SL1 4AX 495 | 157.245.32.0/20,GB,GB-SLG,London,SL1 4AX 496 | 157.245.48.0/20,SG,SG-05,Singapore,627753 497 | 157.245.64.0/20,NL,NL-NH,Amsterdam,1098 XH 498 | 157.245.80.0/20,US,US-NJ,North Bergen,07047 499 | 157.245.96.0/20,IN,IN-KA,Bangalore,560100 500 | 157.245.112.0/20,US,US-NJ,Clifton,07014 501 | 157.245.128.0/20,US,US-NJ,North Bergen,07047 502 | 157.245.144.0/20,SG,SG-05,Singapore,627753 503 | 157.245.160.0/20,US,US-CA,Santa Clara,95051 504 | 157.245.176.0/20,US,US-CA,Santa Clara,95051 505 | 157.245.192.0/20,SG,SG-05,Singapore,627753 506 | 157.245.208.0/20,US,US-NJ,Clifton,07014 507 | 157.245.224.0/20,US,US-CA,Santa Clara,95051 508 | 157.245.240.0/20,US,US-NJ,North Bergen,07047 509 | 159.65.0.0/20,SG,SG-05,Singapore,627753 510 | 159.65.16.0/20,GB,GB-SLG,London,SL1 4AX 511 | 159.65.32.0/20,US,US-NJ,Clifton,07014 512 | 159.65.48.0/20,GB,GB-SLG,London,SL1 4AX 513 | 159.65.64.0/20,US,US-CA,Santa Clara,95051 514 | 159.65.80.0/20,GB,GB-SLG,London,SL1 4AX 515 | 159.65.96.0/20,US,US-CA,Santa Clara,95051 516 | 159.65.112.0/20,DE,DE-HE,Frankfurt,60341 517 | 159.65.128.0/20,SG,SG-05,Singapore,627753 518 | 159.65.144.0/20,IN,IN-KA,Bangalore,560100 519 | 159.65.160.0/20,US,US-NJ,Clifton,07014 520 | 159.65.176.0/20,US,US-NJ,Clifton,07014 521 | 159.65.192.0/20,NL,NL-NH,Amsterdam,1098 XH 522 | 159.65.208.0/22,GB,GB-SLG,London,SL1 4AX 523 | 159.65.212.0/22,GB,GB-SLG,London,SL1 4AX 524 | 159.65.216.0/21,US,US-NJ,North Bergen,07047 525 | 159.65.224.0/20,US,US-NJ,North Bergen,07047 526 | 159.65.240.0/20,US,US-NJ,Clifton,07014 527 | 159.89.0.0/20,DE,DE-HE,Frankfurt,60341 528 | 159.89.16.0/20,DE,DE-HE,Frankfurt,60341 529 | 159.89.32.0/20,US,US-NJ,Clifton,07014 530 | 159.89.48.0/21,US,US-NJ,North Bergen,07047 531 | 159.89.64.0/20,US,US-NJ,North Bergen,07047 532 | 159.89.80.0/20,US,US-NJ,North Bergen,07047 533 | 159.89.96.0/20,DE,DE-HE,Frankfurt,60341 534 | 159.89.112.0/20,CA,CA-ON,Toronto,M5A 0B2 535 | 159.89.128.0/20,US,US-CA,Santa Clara,95051 536 | 159.89.144.0/20,US,US-CA,Santa Clara,95051 537 | 159.89.160.0/20,IN,IN-KA,Bangalore,560100 538 | 159.89.176.0/20,US,US-NJ,Clifton,07014 539 | 159.89.192.0/20,SG,SG-05,Singapore,627753 540 | 159.89.208.0/22,SG,SG-05,Singapore,627753 541 | 159.89.212.0/22,DE,DE-HE,Frankfurt,60341 542 | 159.89.216.0/22,US,US-NY,New York,10011 543 | 159.89.220.0/22,US,US-CA,Santa Clara,95051 544 | 159.89.224.0/20,US,US-NJ,North Bergen,07047 545 | 159.89.240.0/22,US,US-NJ,Clifton,07014 546 | 159.89.244.0/22,US,US-NJ,Clifton,07014 547 | 159.89.248.0/22,GB,GB-SLG,London,SL1 4AX 548 | 159.89.252.0/22,US,US-NJ,Clifton,07014 549 | 159.203.0.0/20,CA,CA-ON,Toronto,M5A 0B2 550 | 159.203.16.0/20,CA,CA-ON,Toronto,M5A 0B2 551 | 159.203.32.0/20,CA,CA-ON,Toronto,M5A 0B2 552 | 159.203.48.0/22,CA,CA-ON,Toronto,M5A 0B2 553 | 159.203.52.0/22,CA,CA-ON,Toronto,M5A 0B2 554 | 159.203.56.0/21,CA,CA-ON,Toronto,M5A 0B2 555 | 159.203.64.0/20,US,US-NJ,Clifton,07014 556 | 159.203.80.0/20,US,US-NJ,Clifton,07014 557 | 159.203.96.0/20,US,US-NJ,Clifton,07014 558 | 159.203.112.0/20,US,US-NJ,Clifton,07014 559 | 159.203.128.0/20,US,US-NJ,Clifton,07014 560 | 159.203.144.0/22,US,US-NJ,Clifton,07014 561 | 159.203.148.0/22,US,US-NJ,Clifton,07014 562 | 159.203.152.0/22,US,US-NY,New York,10011 563 | 159.203.156.0/22,US,US-NJ,North Bergen,07047 564 | 159.203.160.0/20,US,US-NJ,Clifton,07014 565 | 159.203.176.0/20,US,US-NJ,North Bergen,07047 566 | 159.203.192.0/20,US,US-SF,San Francisco,94124 567 | 159.203.208.0/20,US,US-SF,San Francisco,94124 568 | 159.203.224.0/20,US,US-SF,San Francisco,94124 569 | 159.203.240.0/20,US,US-SF,San Francisco,94124 570 | 159.223.0.0/20,NL,NL-NH,Amsterdam,1098 XH 571 | 159.223.16.0/20,DE,DE-HE,Frankfurt,60341 572 | 159.223.32.0/20,SG,SG-05,Singapore,627753 573 | 159.223.48.0/20,SG,SG-05,Singapore,627753 574 | 159.223.64.0/20,SG,SG-05,Singapore,627753 575 | 159.223.80.0/20,SG,SG-05,Singapore,627753 576 | 159.223.96.0/20,US,US-NJ,North Bergen,07047 577 | 159.223.112.0/20,US,US-NJ,North Bergen,07047 578 | 159.223.128.0/20,US,US-NJ,North Bergen,07047 579 | 159.223.144.0/20,US,US-NJ,North Bergen,07047 580 | 159.223.160.0/19,US,US-NJ,North Bergen,07047 581 | 159.223.192.0/20,US,US-CA,Santa Clara,95054 582 | 159.223.208.0/20,NL,NL-NH,Amsterdam,1098 XH 583 | 159.223.224.0/20,NL,NL-NH,Amsterdam,1098 XH 584 | 159.223.240.0/22,NL,NL-NH,Amsterdam,1098 XH 585 | 159.223.244.0/22,GB,GB-SLG,London,SL1 4AX 586 | 159.223.248.0/22,DE,DE-HE,Frankfurt,60341 587 | 161.35.0.0/20,US,US-NJ,North Bergen,07047 588 | 161.35.16.0/20,DE,DE-HE,Frankfurt,60341 589 | 161.35.32.0/20,GB,GB-SLG,London,SL1 4AX 590 | 161.35.48.0/20,US,US-NJ,North Bergen,07047 591 | 161.35.64.0/20,DE,DE-HE,Frankfurt,60341 592 | 161.35.80.0/20,NL,NL-NH,Amsterdam,1098 XH 593 | 161.35.96.0/20,US,US-NJ,North Bergen,07047 594 | 161.35.112.0/20,US,US-NJ,North Bergen,07047 595 | 161.35.128.0/20,US,US-NJ,Clifton,07014 596 | 161.35.144.0/20,NL,NL-NH,Amsterdam,1098 XH 597 | 161.35.160.0/20,GB,GB-SLG,London,SL1 4AX 598 | 161.35.176.0/20,US,US-NJ,Clifton,07014 599 | 161.35.192.0/20,DE,DE-HE,Frankfurt,60341 600 | 161.35.208.0/20,DE,DE-HE,Frankfurt,60341 601 | 161.35.224.0/20,US,US-CA,Santa Clara,95054 602 | 161.35.240.0/22,US,US-CA,Santa Clara,95051 603 | 161.35.244.0/22,NL,NL-NH,Amsterdam,1098 XH 604 | 161.35.248.0/22,US,US-NJ,Clifton,07014 605 | 161.35.252.0/22,US,US-NJ,North Bergen,07047 606 | 162.243.0.0/17,US,US-NY,New York,10011 607 | 162.243.128.0/24,US,US-SF,San Francisco,94124 608 | 162.243.129.0/24,US,US-SF,San Francisco,94124 609 | 162.243.130.0/24,US,US-SF,San Francisco,94124 610 | 162.243.131.0/24,US,US-SF,San Francisco,94124 611 | 162.243.132.0/24,US,US-SF,San Francisco,94124 612 | 162.243.133.0/24,US,US-SF,San Francisco,94124 613 | 162.243.134.0/24,US,US-SF,San Francisco,94124 614 | 162.243.135.0/24,US,US-SF,San Francisco,94124 615 | 162.243.136.0/24,US,US-SF,San Francisco,94124 616 | 162.243.137.0/24,US,US-SF,San Francisco,94124 617 | 162.243.138.0/24,US,US-SF,San Francisco,94124 618 | 162.243.139.0/24,US,US-SF,San Francisco,94124 619 | 162.243.140.0/24,US,US-SF,San Francisco,94124 620 | 162.243.141.0/24,US,US-SF,San Francisco,94124 621 | 162.243.142.0/24,US,US-SF,San Francisco,94124 622 | 162.243.143.0/24,US,US-SF,San Francisco,94124 623 | 162.243.144.0/24,US,US-SF,San Francisco,94124 624 | 162.243.145.0/24,US,US-SF,San Francisco,94124 625 | 162.243.146.0/24,US,US-SF,San Francisco,94124 626 | 162.243.147.0/24,US,US-SF,San Francisco,94124 627 | 162.243.148.0/24,US,US-SF,San Francisco,94124 628 | 162.243.149.0/24,US,US-SF,San Francisco,94124 629 | 162.243.150.0/24,US,US-SF,San Francisco,94124 630 | 162.243.151.0/24,US,US-SF,San Francisco,94124 631 | 162.243.152.0/21,US,US-SF,San Francisco,94124 632 | 162.243.160.0/20,US,US-NJ,North Bergen,07047 633 | 162.243.177.0/24,US,US-NJ,Clifton,07014 634 | 162.243.184.0/22,US,US-NJ,Clifton,07014 635 | 162.243.192.0/18,US,US-NY,New York,10011 636 | 163.47.8.0/22,SG,SG-05,Singapore,627753 637 | 164.90.128.0/20,US,US-NJ,Clifton,07014 638 | 164.90.144.0/20,US,US-CA,Santa Clara,95054 639 | 164.90.160.0/20,DE,DE-HE,Frankfurt,60341 640 | 164.90.176.0/20,DE,DE-HE,Frankfurt,60341 641 | 164.90.192.0/20,NL,NL-NH,Amsterdam,1098 XH 642 | 164.90.208.0/20,DE,DE-HE,Frankfurt,60341 643 | 164.90.224.0/20,DE,DE-HE,Frankfurt,60341 644 | 164.90.240.0/22,DE,DE-HE,Frankfurt,60341 645 | 164.90.244.0/22,US,US-CA,Santa Clara,95054 646 | 164.90.252.0/22,US,US-NJ,North Bergen,07047 647 | 164.92.64.0/19,US,US-CA,Santa Clara,95054 648 | 164.92.96.0/19,US,US-CA,Santa Clara,95054 649 | 164.92.128.0/20,DE,DE-HE,Frankfurt,60341 650 | 164.92.144.0/20,NL,NL-NH,Amsterdam,1098 XH 651 | 164.92.160.0/20,DE,DE-HE,Frankfurt,60341 652 | 164.92.176.0/20,DE,DE-HE,Frankfurt,60341 653 | 164.92.192.0/20,DE,DE-HE,Frankfurt,60341 654 | 164.92.208.0/20,NL,NL-NH,Amsterdam,1098 XH 655 | 164.92.224.0/20,DE,DE-HE,Frankfurt,60341 656 | 164.92.240.0/20,DE,DE-HE,Frankfurt,60341 657 | 165.22.0.0/20,US,US-NJ,North Bergen,07047 658 | 165.22.16.0/20,DE,DE-HE,Frankfurt,60341 659 | 165.22.32.0/20,US,US-NJ,Clifton,07014 660 | 165.22.48.0/20,SG,SG-05,Singapore,627753 661 | 165.22.64.0/20,DE,DE-HE,Frankfurt,60341 662 | 165.22.80.0/20,DE,DE-HE,Frankfurt,60341 663 | 165.22.96.0/20,SG,SG-05,Singapore,627753 664 | 165.22.112.0/20,GB,GB-SLG,London,SL1 4AX 665 | 165.22.128.0/20,US,US-CA,Santa Clara,95051 666 | 165.22.144.0/20,US,US-CA,Santa Clara,95051 667 | 165.22.160.0/20,US,US-CA,Santa Clara,95051 668 | 165.22.176.0/20,US,US-NJ,North Bergen,07047 669 | 165.22.192.0/20,NL,NL-NH,Amsterdam,1098 XH 670 | 165.22.208.0/20,IN,IN-KA,Bangalore,560100 671 | 165.22.224.0/20,CA,CA-ON,Toronto,M5A 0B2 672 | 165.22.240.0/20,SG,SG-05,Singapore,627753 673 | 165.227.0.0/20,US,US-CA,Santa Clara,95051 674 | 165.227.16.0/20,US,US-CA,Santa Clara,95051 675 | 165.227.32.0/20,CA,CA-ON,Toronto,M5A 0B2 676 | 165.227.48.0/20,US,US-CA,Santa Clara,95051 677 | 165.227.64.0/20,US,US-NJ,Clifton,07014 678 | 165.227.80.0/20,US,US-NJ,North Bergen,07047 679 | 165.227.96.0/20,US,US-NJ,Clifton,07014 680 | 165.227.112.0/20,US,US-NJ,Clifton,07014 681 | 165.227.128.0/20,DE,DE-HE,Frankfurt,60341 682 | 165.227.144.0/20,DE,DE-HE,Frankfurt,60341 683 | 165.227.160.0/20,DE,DE-HE,Frankfurt,60341 684 | 165.227.176.0/20,US,US-NJ,Clifton,07014 685 | 165.227.192.0/20,US,US-NJ,North Bergen,07047 686 | 165.227.208.0/20,US,US-NJ,Clifton,07014 687 | 165.227.224.0/20,GB,GB-SLG,London,SL1 4AX 688 | 165.227.240.0/22,US,US-CA,Santa Clara,95051 689 | 165.227.244.0/22,DE,DE-HE,Frankfurt,60341 690 | 165.227.248.0/22,US,US-NJ,Clifton,07014 691 | 165.227.252.0/22,US,US-NJ,North Bergen,07047 692 | 165.232.32.0/20,GB,GB-SLG,London,SL1 4AX 693 | 165.232.48.0/20,US,US-CA,Santa Clara,95051 694 | 165.232.64.0/20,DE,DE-HE,Frankfurt,60341 695 | 165.232.80.0/20,NL,NL-NH,Amsterdam,1098 XH 696 | 165.232.96.0/20,GB,GB-SLG,London,SL1 4AX 697 | 165.232.112.0/20,DE,DE-HE,Frankfurt,60341 698 | 165.232.128.0/20,US,US-CA,Santa Clara,95054 699 | 165.232.144.0/20,US,US-CA,Santa Clara,95054 700 | 165.232.160.0/20,SG,SG-05,Singapore,627753 701 | 165.232.176.0/20,IN,IN-KA,Bangalore,560100 702 | 167.71.0.0/20,NL,NL-NH,Amsterdam,1098 XH 703 | 167.71.16.0/20,US,US-NJ,North Bergen,07047 704 | 167.71.32.0/20,DE,DE-HE,Frankfurt,60341 705 | 167.71.48.0/20,DE,DE-HE,Frankfurt,60341 706 | 167.71.64.0/20,NL,NL-NH,Amsterdam,1098 XH 707 | 167.71.80.0/20,US,US-NJ,Clifton,07014 708 | 167.71.96.0/20,US,US-NJ,Clifton,07014 709 | 167.71.112.0/20,US,US-CA,Santa Clara,95051 710 | 167.71.128.0/20,GB,GB-SLG,London,SL1 4AX 711 | 167.71.144.0/20,US,US-CA,Santa Clara,95051 712 | 167.71.160.0/20,US,US-NJ,Clifton,07014 713 | 167.71.176.0/20,US,US-NJ,Clifton,07014 714 | 167.71.192.0/20,SG,SG-05,Singapore,627753 715 | 167.71.208.0/20,SG,SG-05,Singapore,627753 716 | 167.71.224.0/20,IN,IN-KA,Bangalore,560100 717 | 167.71.240.0/20,US,US-NJ,Clifton,07014 718 | 167.99.0.0/20,US,US-NJ,North Bergen,07047 719 | 167.99.16.0/22,NL,NL-NH,Amsterdam,1098 XH 720 | 167.99.20.0/22,US,US-NJ,Clifton,07014 721 | 167.99.24.0/22,US,US-CA,Santa Clara,95051 722 | 167.99.28.0/22,SG,SG-05,Singapore,627753 723 | 167.99.32.0/20,NL,NL-NH,Amsterdam,1098 XH 724 | 167.99.48.0/20,US,US-NJ,Clifton,07014 725 | 167.99.64.0/20,SG,SG-05,Singapore,627753 726 | 167.99.80.0/20,GB,GB-SLG,London,SL1 4AX 727 | 167.99.96.0/20,US,US-CA,Santa Clara,95051 728 | 167.99.112.0/20,US,US-NJ,Clifton,07014 729 | 167.99.128.0/20,DE,DE-HE,Frankfurt,60341 730 | 167.99.144.0/20,US,US-NJ,North Bergen,07047 731 | 167.99.160.0/20,US,US-CA,Santa Clara,95051 732 | 167.99.176.0/20,CA,CA-ON,Toronto,M5A 0B2 733 | 167.99.192.0/20,GB,GB-SLG,London,SL1 4AX 734 | 167.99.208.0/20,NL,NL-NH,Amsterdam,1098 XH 735 | 167.99.224.0/20,US,US-NJ,North Bergen,07047 736 | 167.99.240.0/20,DE,DE-HE,Frankfurt,60341 737 | 167.172.0.0/22,US,US-NJ,North Bergen,07047 738 | 167.172.4.0/22,SG,SG-05,Singapore,627753 739 | 167.172.8.0/22,US,US-CA,Santa Clara,95051 740 | 167.172.12.0/22,US,US-NJ,North Bergen,07047 741 | 167.172.16.0/20,US,US-NJ,Clifton,07014 742 | 167.172.32.0/20,NL,NL-NH,Amsterdam,1098 XH 743 | 167.172.48.0/20,GB,GB-SLG,London,SL1 4AX 744 | 167.172.64.0/20,SG,SG-05,Singapore,627753 745 | 167.172.80.0/20,SG,SG-05,Singapore,627753 746 | 167.172.96.0/20,DE,DE-HE,Frankfurt,60341 747 | 167.172.112.0/20,US,US-CA,Santa Clara,95051 748 | 167.172.128.0/20,US,US-NJ,North Bergen,07047 749 | 167.172.144.0/20,US,US-NJ,North Bergen,07047 750 | 167.172.160.0/20,DE,DE-HE,Frankfurt,60341 751 | 167.172.176.0/20,DE,DE-HE,Frankfurt,60341 752 | 167.172.192.0/20,US,US-CA,Santa Clara,95051 753 | 167.172.208.0/20,US,US-CA,Santa Clara,95051 754 | 167.172.224.0/20,US,US-NJ,Clifton,07014 755 | 167.172.240.0/20,US,US-NJ,Clifton,07014 756 | 170.64.128.0/18,AU,AU-NSW,Sydney,2015 757 | 170.64.192.0/19,AU,AU-NSW,Sydney,2015 758 | 170.64.224.0/20,AU,AU-NSW,Sydney,2015 759 | 170.64.240.0/21,AU,AU-NSW,Sydney,2015 760 | 170.64.248.0/21,AU,AU-NSW,Sydney,2015 761 | 174.138.0.0/20,NL,NL-NH,Amsterdam,1098 XH 762 | 174.138.16.0/20,SG,SG-05,Singapore,627753 763 | 174.138.32.0/20,US,US-NJ,North Bergen,07047 764 | 174.138.48.0/20,US,US-NJ,Clifton,07014 765 | 174.138.64.0/20,US,US-NJ,Clifton,07014 766 | 174.138.80.0/20,US,US-NJ,Clifton,07014 767 | 174.138.96.0/22,NL,NL-NH,Amsterdam,1098 XH 768 | 174.138.100.0/22,DE,DE-HE,Frankfurt,60341 769 | 174.138.104.0/22,NL,NL-NH,Amsterdam,1098 XH 770 | 174.138.108.0/22,US,US-NJ,North Bergen,07047 771 | 174.138.112.0/22,CA,CA-ON,Toronto,M5A 0B2 772 | 174.138.116.0/22,US,US-NJ,Clifton,07014 773 | 174.138.120.0/22,IN,IN-KA,Bangalore,560100 774 | 174.138.124.0/22,US,US-NJ,North Bergen,07047 775 | 178.62.0.0/18,GB,GB-SLG,London,SL1 4AX 776 | 178.62.64.0/18,GB,GB-SLG,London,SL1 4AX 777 | 178.62.128.0/18,NL,NL-NH,Amsterdam,1098 XH 778 | 178.62.192.0/18,NL,NL-NH,Amsterdam,1098 XH 779 | 178.128.0.0/20,US,US-CA,Santa Clara,95051 780 | 178.128.16.0/20,SG,SG-05,Singapore,627753 781 | 178.128.32.0/20,GB,GB-SLG,London,SL1 4AX 782 | 178.128.48.0/20,SG,SG-05,Singapore,627753 783 | 178.128.64.0/20,US,US-CA,Santa Clara,95051 784 | 178.128.80.0/20,SG,SG-05,Singapore,627753 785 | 178.128.96.0/20,SG,SG-05,Singapore,627753 786 | 178.128.112.0/20,SG,SG-05,Singapore,627753 787 | 178.128.128.0/22,US,US-CA,Santa Clara,95051 788 | 178.128.132.0/22,US,US-NJ,North Bergen,07047 789 | 178.128.136.0/22,NL,NL-NH,Amsterdam,1098 XH 790 | 178.128.140.0/22,NL,NL-NH,Amsterdam,1098 XH 791 | 178.128.144.0/20,US,US-NJ,North Bergen,07047 792 | 178.128.160.0/20,GB,GB-SLG,London,SL1 4AX 793 | 178.128.176.0/20,US,US-CA,Santa Clara,95051 794 | 178.128.192.0/20,DE,DE-HE,Frankfurt,60341 795 | 178.128.208.0/20,SG,SG-05,Singapore,627753 796 | 178.128.224.0/20,CA,CA-ON,Toronto,M5A 0B2 797 | 178.128.240.0/20,NL,NL-NH,Amsterdam,1098 XH 798 | 185.14.184.0/22,NL,NL-NH,Amsterdam,1098 XH 799 | 188.166.0.0/18,NL,NL-NH,Amsterdam,1098 XH 800 | 188.166.64.0/18,NL,NL-NH,Amsterdam,1098 XH 801 | 188.166.128.0/22,NL,NL-NH,Amsterdam,1098 XH 802 | 188.166.132.0/22,NL,NL-NH,Amsterdam,1098 XH 803 | 188.166.136.0/22,GB,GB-SLG,London,SL1 4AX 804 | 188.166.140.0/22,NL,NL-NH,Amsterdam,1098 XH 805 | 188.166.144.0/20,GB,GB-SLG,London,SL1 4AX 806 | 188.166.160.0/21,DE,DE-HE,Frankfurt,60341 807 | 188.166.168.0/21,GB,GB-SLG,London,SL1 4AX 808 | 188.166.176.0/20,SG,SG-05,Singapore,627753 809 | 188.166.192.0/22,DE,DE-HE,Frankfurt,60341 810 | 188.166.196.0/22,SG,SG-05,Singapore,627753 811 | 188.166.200.0/22,NL,NL-NH,Amsterdam,1098 XH 812 | 188.166.204.0/22,SG,SG-05,Singapore,627753 813 | 188.166.208.0/20,SG,SG-05,Singapore,627753 814 | 188.166.224.0/20,SG,SG-05,Singapore,627753 815 | 188.166.240.0/20,SG,SG-05,Singapore,627753 816 | 188.226.128.0/17,NL,NL-NH,Amsterdam,1098 XH 817 | 192.34.56.0/21,US,US-NJ,North Bergen,07047 818 | 192.81.208.0/21,US,US-NJ,North Bergen,07047 819 | 192.81.216.0/22,US,US-NJ,North Bergen,07047 820 | 192.81.220.0/22,NL,NL-NH,Amsterdam,1098 XH 821 | 192.241.128.0/19,US,US-NJ,North Bergen,07047 822 | 192.241.160.0/24,US,US-NY,New York,10011 823 | 192.241.161.0/24,US,US-NY,New York,10011 824 | 192.241.162.0/24,US,US-NY,New York,10011 825 | 192.241.163.0/24,US,US-NY,New York,10011 826 | 192.241.165.0/24,US,US-NY,New York,10011 827 | 192.241.166.0/24,US,US-NY,New York,10011 828 | 192.241.167.0/24,US,US-NY,New York,10011 829 | 192.241.168.0/24,US,US-NY,New York,10011 830 | 192.241.169.0/24,US,US-NY,New York,10011 831 | 192.241.170.0/24,US,US-NY,New York,10011 832 | 192.241.171.0/24,US,US-NY,New York,10011 833 | 192.241.172.0/24,US,US-NY,New York,10011 834 | 192.241.173.0/24,US,US-NY,New York,10011 835 | 192.241.174.0/24,US,US-NY,New York,10011 836 | 192.241.175.0/24,US,US-NY,New York,10011 837 | 192.241.176.0/24,US,US-NY,New York,10011 838 | 192.241.177.0/24,US,US-NY,New York,10011 839 | 192.241.178.0/24,US,US-NY,New York,10011 840 | 192.241.179.0/24,US,US-NY,New York,10011 841 | 192.241.180.0/24,US,US-NY,New York,10011 842 | 192.241.181.0/24,US,US-NY,New York,10011 843 | 192.241.182.0/24,US,US-NY,New York,10011 844 | 192.241.183.0/24,US,US-NY,New York,10011 845 | 192.241.184.0/24,US,US-NY,New York,10011 846 | 192.241.185.0/24,US,US-NY,New York,10011 847 | 192.241.186.0/24,US,US-NY,New York,10011 848 | 192.241.187.0/24,US,US-NY,New York,10011 849 | 192.241.188.0/24,US,US-NY,New York,10011 850 | 192.241.189.0/24,US,US-NY,New York,10011 851 | 192.241.190.0/24,US,US-NY,New York,10011 852 | 192.241.191.0/24,US,US-NY,New York,10011 853 | 192.241.192.0/24,US,US-SF,San Francisco,94124 854 | 192.241.193.0/24,US,US-SF,San Francisco,94124 855 | 192.241.194.0/24,US,US-SF,San Francisco,94124 856 | 192.241.195.0/24,US,US-SF,San Francisco,94124 857 | 192.241.196.0/24,US,US-SF,San Francisco,94124 858 | 192.241.197.0/24,US,US-SF,San Francisco,94124 859 | 192.241.198.0/24,US,US-SF,San Francisco,94124 860 | 192.241.199.0/24,US,US-SF,San Francisco,94124 861 | 192.241.200.0/24,US,US-SF,San Francisco,94124 862 | 192.241.201.0/24,US,US-SF,San Francisco,94124 863 | 192.241.202.0/24,US,US-SF,San Francisco,94124 864 | 192.241.203.0/24,US,US-SF,San Francisco,94124 865 | 192.241.204.0/24,US,US-SF,San Francisco,94124 866 | 192.241.205.0/24,US,US-SF,San Francisco,94124 867 | 192.241.206.0/24,US,US-SF,San Francisco,94124 868 | 192.241.207.0/24,US,US-SF,San Francisco,94124 869 | 192.241.208.0/24,US,US-SF,San Francisco,94124 870 | 192.241.209.0/24,US,US-SF,San Francisco,94124 871 | 192.241.210.0/24,US,US-SF,San Francisco,94124 872 | 192.241.211.0/24,US,US-SF,San Francisco,94124 873 | 192.241.212.0/24,US,US-SF,San Francisco,94124 874 | 192.241.213.0/24,US,US-SF,San Francisco,94124 875 | 192.241.214.0/24,US,US-SF,San Francisco,94124 876 | 192.241.215.0/24,US,US-SF,San Francisco,94124 877 | 192.241.216.0/24,US,US-SF,San Francisco,94124 878 | 192.241.217.0/24,US,US-SF,San Francisco,94124 879 | 192.241.218.0/24,US,US-SF,San Francisco,94124 880 | 192.241.219.0/24,US,US-SF,San Francisco,94124 881 | 192.241.220.0/24,US,US-SF,San Francisco,94124 882 | 192.241.221.0/24,US,US-SF,San Francisco,94124 883 | 192.241.222.0/24,US,US-SF,San Francisco,94124 884 | 192.241.223.0/24,US,US-SF,San Francisco,94124 885 | 192.241.224.0/24,US,US-SF,San Francisco,94124 886 | 192.241.225.0/24,US,US-SF,San Francisco,94124 887 | 192.241.226.0/24,US,US-SF,San Francisco,94124 888 | 192.241.227.0/24,US,US-SF,San Francisco,94124 889 | 192.241.228.0/24,US,US-SF,San Francisco,94124 890 | 192.241.229.0/24,US,US-SF,San Francisco,94124 891 | 192.241.230.0/24,US,US-SF,San Francisco,94124 892 | 192.241.231.0/24,US,US-SF,San Francisco,94124 893 | 192.241.232.0/24,US,US-SF,San Francisco,94124 894 | 192.241.233.0/24,US,US-SF,San Francisco,94124 895 | 192.241.234.0/24,US,US-SF,San Francisco,94124 896 | 192.241.235.0/24,US,US-SF,San Francisco,94124 897 | 192.241.236.0/24,US,US-SF,San Francisco,94124 898 | 192.241.237.0/24,US,US-SF,San Francisco,94124 899 | 192.241.238.0/24,US,US-SF,San Francisco,94124 900 | 192.241.239.0/24,US,US-SF,San Francisco,94124 901 | 192.241.240.0/20,US,US-NY,New York,10011 902 | 198.199.64.0/20,US,US-NJ,North Bergen,07047 903 | 198.199.80.0/21,US,US-NJ,North Bergen,07047 904 | 198.199.88.0/22,US,US-NJ,North Bergen,07047 905 | 198.199.92.0/24,US,US-SF,San Francisco,94124 906 | 198.199.93.0/24,US,US-SF,San Francisco,94124 907 | 198.199.94.0/24,US,US-SF,San Francisco,94124 908 | 198.199.95.0/24,US,US-SF,San Francisco,94124 909 | 198.199.96.0/24,US,US-SF,San Francisco,94124 910 | 198.199.97.0/24,US,US-SF,San Francisco,94124 911 | 198.199.98.0/24,US,US-SF,San Francisco,94124 912 | 198.199.100.0/24,US,US-SF,San Francisco,94124 913 | 198.199.101.0/24,US,US-SF,San Francisco,94124 914 | 198.199.102.0/24,US,US-SF,San Francisco,94124 915 | 198.199.103.0/24,US,US-SF,San Francisco,94124 916 | 198.199.104.0/24,US,US-SF,San Francisco,94124 917 | 198.199.105.0/24,US,US-SF,San Francisco,94124 918 | 198.199.106.0/24,US,US-SF,San Francisco,94124 919 | 198.199.107.0/24,US,US-SF,San Francisco,94124 920 | 198.199.108.0/24,US,US-SF,San Francisco,94124 921 | 198.199.109.0/24,US,US-SF,San Francisco,94124 922 | 198.199.110.0/24,US,US-SF,San Francisco,94124 923 | 198.199.111.0/24,US,US-SF,San Francisco,94124 924 | 198.199.112.0/24,US,US-SF,San Francisco,94124 925 | 198.199.113.0/24,US,US-SF,San Francisco,94124 926 | 198.199.114.0/24,US,US-SF,San Francisco,94124 927 | 198.199.115.0/24,US,US-SF,San Francisco,94124 928 | 198.199.116.0/24,US,US-SF,San Francisco,94124 929 | 198.199.117.0/24,US,US-SF,San Francisco,94124 930 | 198.199.118.0/24,US,US-SF,San Francisco,94124 931 | 198.199.119.0/24,US,US-SF,San Francisco,94124 932 | 198.199.120.0/22,US,US-NJ,North Bergen,07047 933 | 198.199.124.0/22,NL,NL-NH,Amsterdam,1098 XH 934 | 198.211.96.0/24,US,US-NJ,North Bergen,07047 935 | 198.211.97.0/24,US,US-NJ,North Bergen,07047 936 | 198.211.98.0/24,US,US-NJ,North Bergen,07047 937 | 198.211.99.0/24,US,US-NJ,North Bergen,07047 938 | 198.211.100.0/24,US,US-NJ,North Bergen,07047 939 | 198.211.101.0/24,US,US-NJ,North Bergen,07047 940 | 198.211.102.0/24,US,US-NJ,North Bergen,07047 941 | 198.211.103.0/24,US,US-NJ,North Bergen,07047 942 | 198.211.104.0/24,US,US-NJ,North Bergen,07047 943 | 198.211.105.0/24,US,US-NJ,North Bergen,07047 944 | 198.211.106.0/24,US,US-NJ,North Bergen,07047 945 | 198.211.107.0/24,US,US-NJ,North Bergen,07047 946 | 198.211.108.0/24,US,US-NJ,North Bergen,07047 947 | 198.211.109.0/24,US,US-NJ,North Bergen,07047 948 | 198.211.110.0/24,US,US-NJ,North Bergen,07047 949 | 198.211.112.0/22,US,US-NJ,North Bergen,07047 950 | 198.211.116.0/23,US,US-NJ,North Bergen,07047 951 | 198.211.118.0/23,NL,NL-NH,Amsterdam,1098 XH 952 | 198.211.120.0/21,NL,NL-NH,Amsterdam,1098 XH 953 | 204.48.16.0/20,US,US-NJ,North Bergen,07047 954 | 206.81.0.0/20,US,US-NJ,North Bergen,07047 955 | 206.81.16.0/20,DE,DE-HE,Frankfurt,60341 956 | 206.189.0.0/20,NL,NL-NH,Amsterdam,1098 XH 957 | 206.189.16.0/20,GB,GB-SLG,London,SL1 4AX 958 | 206.189.32.0/20,SG,SG-05,Singapore,627753 959 | 206.189.48.0/20,DE,DE-HE,Frankfurt,60341 960 | 206.189.64.0/20,US,US-CA,Santa Clara,95051 961 | 206.189.80.0/20,SG,SG-05,Singapore,627753 962 | 206.189.96.0/20,NL,NL-NH,Amsterdam,1098 XH 963 | 206.189.112.0/20,GB,GB-SLG,London,SL1 4AX 964 | 206.189.128.0/20,IN,IN-KA,Bangalore,560100 965 | 206.189.144.0/20,SG,SG-05,Singapore,627753 966 | 206.189.160.0/20,US,US-CA,Santa Clara,95051 967 | 206.189.176.0/20,US,US-NJ,North Bergen,07047 968 | 206.189.192.0/20,US,US-NJ,North Bergen,07047 969 | 206.189.208.0/20,US,US-CA,Santa Clara,95051 970 | 206.189.224.0/20,US,US-NJ,North Bergen,07047 971 | 206.189.240.0/22,NL,NL-NH,Amsterdam,1098 XH 972 | 206.189.244.0/22,GB,GB-SLG,London,SL1 4AX 973 | 206.189.248.0/22,DE,DE-HE,Frankfurt,60341 974 | 206.189.252.0/22,US,US-NJ,North Bergen,07047 975 | 207.154.192.0/20,DE,DE-HE,Frankfurt,60341 976 | 207.154.208.0/20,DE,DE-HE,Frankfurt,60341 977 | 207.154.224.0/20,DE,DE-HE,Frankfurt,60341 978 | 207.154.240.0/20,DE,DE-HE,Frankfurt,60341 979 | 208.68.36.0/22,US,US-NJ,North Bergen,07047 980 | 209.38.0.0/22,CA,CA-ON,Toronto,M5A 0B2 981 | 209.38.4.0/22,US,US-CA,Santa Clara,95054 982 | 209.38.8.0/21,CA,CA-ON,Toronto,M5A 0B2 983 | 209.38.16.0/20,AU,AU-NSW,Sydney,2015 984 | 209.38.32.0/20,NL,NL-NH,Amsterdam,1098 XH 985 | 209.38.48.0/22,US,US-NJ,Clifton,07014 986 | 209.38.64.0/20,US,US-CA,Santa Clara,95054 987 | 209.38.96.0/20,NL,NL-NH,Amsterdam,1098 XH 988 | 209.38.128.0/19,US,US-CA,Santa Clara,95054 989 | 209.38.160.0/22,GB,GB-SLG,London,SL1 4AX 990 | 209.38.164.0/22,GB,GB-SLG,London,SL1 4AX 991 | 209.38.168.0/22,GB,GB-SLG,London,SL1 4AX 992 | 209.38.172.0/22,US,US-CA,Santa Clara,95054 993 | 209.38.176.0/20,DE,DE-HE,Frankfurt,60341 994 | 209.38.192.0/19,DE,DE-HE,Frankfurt,60341 995 | 209.38.224.0/19,DE,DE-HE,Frankfurt,60341 996 | 209.97.128.0/20,GB,GB-SLG,London,SL1 4AX 997 | 209.97.144.0/20,US,US-NJ,Clifton,07014 998 | 209.97.160.0/20,SG,SG-05,Singapore,627753 999 | 209.97.176.0/20,GB,GB-SLG,London,SL1 4AX 1000 | 2400:6180:0:d0::/64,SG,SG-05,Singapore,627753 1001 | 2400:6180:0:d1::/64,SG,SG-05,Singapore,627753 1002 | 2400:6180:0:d2::/64,SG,SG-05,Singapore,627753 1003 | 2400:6180:0:d3::/64,SG,SG-05,Singapore,627753 1004 | 2400:6180:10:200::/64,AU,AU-NSW,Sydney,2015 1005 | 2400:6180:100:d0::/64,IN,IN-KA,Bangalore,560100 1006 | 2604:a880:0:1010::/64,US,US-NY,New York,10011 1007 | 2604:a880:0:1011::/64,US,US-NY,New York,10011 1008 | 2604:a880:0:1012::/64,US,US-NY,New York,10011 1009 | 2604:a880:0:1013::/64,US,US-NY,New York,10011 1010 | 2604:a880:0:1014::/64,US,US-NY,New York,10011 1011 | 2604:a880:0:1015::/64,US,US-NY,New York,10011 1012 | 2604:a880:0:1016::/64,US,US-NY,New York,10011 1013 | 2604:a880:0:1017::/64,US,US-NY,New York,10011 1014 | 2604:a880:0:1018::/64,US,US-NY,New York,10011 1015 | 2604:a880:0:1019::/64,US,US-NY,New York,10011 1016 | 2604:a880:0:1020::/64,US,US-NY,New York,10011 1017 | 2604:a880:0:1021::/64,US,US-NY,New York,10011 1018 | 2604:a880:0:1022::/64,US,US-NY,New York,10011 1019 | 2604:a880:0:1023::/64,US,US-NY,New York,10011 1020 | 2604:a880:0:1024::/64,US,US-NY,New York,10011 1021 | 2604:a880:0:1025::/64,US,US-NY,New York,10011 1022 | 2604:a880:0:1026::/64,US,US-NY,New York,10011 1023 | 2604:a880:0:1027::/64,US,US-NY,New York,10011 1024 | 2604:a880:0:1028::/64,US,US-NY,New York,10011 1025 | 2604:a880:0:1029::/64,US,US-NY,New York,10011 1026 | 2604:a880:0:2010::/64,US,US-NY,New York,10011 1027 | 2604:a880:0:2011::/64,US,US-NY,New York,10011 1028 | 2604:a880:0:2012::/64,US,US-NY,New York,10011 1029 | 2604:a880:0:2013::/64,US,US-NY,New York,10011 1030 | 2604:a880:0:2014::/64,US,US-NY,New York,10011 1031 | 2604:a880:0:2015::/64,US,US-NY,New York,10011 1032 | 2604:a880:0:2016::/64,US,US-NY,New York,10011 1033 | 2604:a880:0:2017::/64,US,US-NY,New York,10011 1034 | 2604:a880:0:2018::/64,US,US-NY,New York,10011 1035 | 2604:a880:0:2019::/64,US,US-NY,New York,10011 1036 | 2604:a880:0:2020::/64,US,US-NY,New York,10011 1037 | 2604:a880:0:2021::/64,US,US-NY,New York,10011 1038 | 2604:a880:0:2022::/64,US,US-NY,New York,10011 1039 | 2604:a880:0:2023::/64,US,US-NY,New York,10011 1040 | 2604:a880:0:2024::/64,US,US-NY,New York,10011 1041 | 2604:a880:0:2025::/64,US,US-NY,New York,10011 1042 | 2604:a880:0:2026::/64,US,US-NY,New York,10011 1043 | 2604:a880:0:2027::/64,US,US-NY,New York,10011 1044 | 2604:a880:0:2028::/64,US,US-NY,New York,10011 1045 | 2604:a880:0:2029::/64,US,US-NY,New York,10011 1046 | 2604:a880:0:202a::/64,US,US-NY,New York,10011 1047 | 2604:a880:1:20::/64,US,US-SF,San Francisco,94124 1048 | 2604:a880:1:4a::/64,US,US-SF,San Francisco,94124 1049 | 2604:a880:2:d0::/64,US,US-CA,Santa Clara,95051 1050 | 2604:a880:2:d1::/64,US,US-CA,Santa Clara,95051 1051 | 2604:a880:4:1d0::/64,US,US-CA,Santa Clara,95054 1052 | 2604:a880:400:d0::/64,US,US-NJ,North Bergen,07047 1053 | 2604:a880:400:d1::/64,US,US-NJ,North Bergen,07047 1054 | 2604:a880:800:10::/64,US,US-NJ,Clifton,07014 1055 | 2604:a880:800:11::/64,US,US-NJ,Clifton,07014 1056 | 2604:a880:800:12::/64,US,US-NJ,Clifton,07014 1057 | 2604:a880:800:13::/64,US,US-NJ,Clifton,07014 1058 | 2604:a880:800:14::/64,US,US-NJ,Clifton,07014 1059 | 2604:a880:800:a1::/64,US,US-NJ,Clifton,07014 1060 | 2604:a880:800:c1::/64,US,US-NJ,Clifton,07014 1061 | 2604:a880:cad:d0::/64,CA,CA-ON,Toronto,M5A 0B2 1062 | 2a03:b0c0:0:108::/64,NL,NL-NH,Amsterdam,1098 XH 1063 | 2a03:b0c0:0:126::/64,NL,NL-NH,Amsterdam,1098 XH 1064 | 2a03:b0c0:0:127::/64,NL,NL-NH,Amsterdam,1098 XH 1065 | 2a03:b0c0:0:128::/64,NL,NL-NH,Amsterdam,1098 XH 1066 | 2a03:b0c0:0:129::/64,NL,NL-NH,Amsterdam,1098 XH 1067 | 2a03:b0c0:0:130::/64,NL,NL-NH,Amsterdam,1098 XH 1068 | 2a03:b0c0:0:131::/64,NL,NL-NH,Amsterdam,1098 XH 1069 | 2a03:b0c0:0:132::/64,NL,NL-NH,Amsterdam,1098 XH 1070 | 2a03:b0c0:0:133::/64,NL,NL-NH,Amsterdam,1098 XH 1071 | 2a03:b0c0:0:134::/64,NL,NL-NH,Amsterdam,1098 XH 1072 | 2a03:b0c0:0:135::/64,NL,NL-NH,Amsterdam,1098 XH 1073 | 2a03:b0c0:0:136::/64,NL,NL-NH,Amsterdam,1098 XH 1074 | 2a03:b0c0:0:137::/64,NL,NL-NH,Amsterdam,1098 XH 1075 | 2a03:b0c0:0:138::/64,NL,NL-NH,Amsterdam,1098 XH 1076 | 2a03:b0c0:0:139::/64,NL,NL-NH,Amsterdam,1098 XH 1077 | 2a03:b0c0:0:140::/64,NL,NL-NH,Amsterdam,1098 XH 1078 | 2a03:b0c0:0:141::/64,NL,NL-NH,Amsterdam,1098 XH 1079 | 2a03:b0c0:0:142::/64,NL,NL-NH,Amsterdam,1098 XH 1080 | 2a03:b0c0:0:143::/64,NL,NL-NH,Amsterdam,1098 XH 1081 | 2a03:b0c0:0:144::/64,NL,NL-NH,Amsterdam,1098 XH 1082 | 2a03:b0c0:0:145::/64,NL,NL-NH,Amsterdam,1098 XH 1083 | 2a03:b0c0:0:146::/64,NL,NL-NH,Amsterdam,1098 XH 1084 | 2a03:b0c0:0:147::/64,NL,NL-NH,Amsterdam,1098 XH 1085 | 2a03:b0c0:0:148::/64,NL,NL-NH,Amsterdam,1098 XH 1086 | 2a03:b0c0:0:149::/64,NL,NL-NH,Amsterdam,1098 XH 1087 | 2a03:b0c0:0:150::/64,NL,NL-NH,Amsterdam,1098 XH 1088 | 2a03:b0c0:0:151::/64,NL,NL-NH,Amsterdam,1098 XH 1089 | 2a03:b0c0:0:152::/64,NL,NL-NH,Amsterdam,1098 XH 1090 | 2a03:b0c0:0:153::/64,NL,NL-NH,Amsterdam,1098 XH 1091 | 2a03:b0c0:0:154::/64,NL,NL-NH,Amsterdam,1098 XH 1092 | 2a03:b0c0:0:155::/64,NL,NL-NH,Amsterdam,1098 XH 1093 | 2a03:b0c0:0:1010::/64,NL,NL-NH,Amsterdam,1098 XH 1094 | 2a03:b0c0:0:1011::/64,NL,NL-NH,Amsterdam,1098 XH 1095 | 2a03:b0c0:0:1012::/64,NL,NL-NH,Amsterdam,1098 XH 1096 | 2a03:b0c0:0:1013::/64,NL,NL-NH,Amsterdam,1098 XH 1097 | 2a03:b0c0:0:1014::/64,NL,NL-NH,Amsterdam,1098 XH 1098 | 2a03:b0c0:0:1015::/64,NL,NL-NH,Amsterdam,1098 XH 1099 | 2a03:b0c0:0:1016::/64,NL,NL-NH,Amsterdam,1098 XH 1100 | 2a03:b0c0:0:1017::/64,NL,NL-NH,Amsterdam,1098 XH 1101 | 2a03:b0c0:0:1018::/64,NL,NL-NH,Amsterdam,1098 XH 1102 | 2a03:b0c0:0:1019::/64,NL,NL-NH,Amsterdam,1098 XH 1103 | 2a03:b0c0:0:1020::/64,NL,NL-NH,Amsterdam,1098 XH 1104 | 2a03:b0c0:0:1021::/64,NL,NL-NH,Amsterdam,1098 XH 1105 | 2a03:b0c0:0:1022::/64,NL,NL-NH,Amsterdam,1098 XH 1106 | 2a03:b0c0:0:1023::/64,NL,NL-NH,Amsterdam,1098 XH 1107 | 2a03:b0c0:0:1024::/64,NL,NL-NH,Amsterdam,1098 XH 1108 | 2a03:b0c0:0:1025::/64,NL,NL-NH,Amsterdam,1098 XH 1109 | 2a03:b0c0:0:1026::/64,NL,NL-NH,Amsterdam,1098 XH 1110 | 2a03:b0c0:0:1027::/64,NL,NL-NH,Amsterdam,1098 XH 1111 | 2a03:b0c0:0:1028::/64,NL,NL-NH,Amsterdam,1098 XH 1112 | 2a03:b0c0:0:1029::/64,NL,NL-NH,Amsterdam,1098 XH 1113 | 2a03:b0c0:0:1030::/64,NL,NL-NH,Amsterdam,1098 XH 1114 | 2a03:b0c0:0:1031::/64,NL,NL-NH,Amsterdam,1098 XH 1115 | 2a03:b0c0:0:1032::/64,NL,NL-NH,Amsterdam,1098 XH 1116 | 2a03:b0c0:0:1033::/64,NL,NL-NH,Amsterdam,1098 XH 1117 | 2a03:b0c0:0:1034::/64,NL,NL-NH,Amsterdam,1098 XH 1118 | 2a03:b0c0:0:1035::/64,NL,NL-NH,Amsterdam,1098 XH 1119 | 2a03:b0c0:0:1036::/64,NL,NL-NH,Amsterdam,1098 XH 1120 | 2a03:b0c0:0:1037::/64,NL,NL-NH,Amsterdam,1098 XH 1121 | 2a03:b0c0:0:1038::/64,NL,NL-NH,Amsterdam,1098 XH 1122 | 2a03:b0c0:0:1039::/64,NL,NL-NH,Amsterdam,1098 XH 1123 | 2a03:b0c0:0:1040::/64,NL,NL-NH,Amsterdam,1098 XH 1124 | 2a03:b0c0:0:1041::/64,NL,NL-NH,Amsterdam,1098 XH 1125 | 2a03:b0c0:0:1042::/64,NL,NL-NH,Amsterdam,1098 XH 1126 | 2a03:b0c0:0:1043::/64,NL,NL-NH,Amsterdam,1098 XH 1127 | 2a03:b0c0:0:1044::/64,NL,NL-NH,Amsterdam,1098 XH 1128 | 2a03:b0c0:0:1045::/64,NL,NL-NH,Amsterdam,1098 XH 1129 | 2a03:b0c0:0:1046::/64,NL,NL-NH,Amsterdam,1098 XH 1130 | 2a03:b0c0:0:1047::/64,NL,NL-NH,Amsterdam,1098 XH 1131 | 2a03:b0c0:0:1048::/64,NL,NL-NH,Amsterdam,1098 XH 1132 | 2a03:b0c0:0:1049::/64,NL,NL-NH,Amsterdam,1098 XH 1133 | 2a03:b0c0:0:1050::/64,NL,NL-NH,Amsterdam,1098 XH 1134 | 2a03:b0c0:0:1051::/64,NL,NL-NH,Amsterdam,1098 XH 1135 | 2a03:b0c0:1:a1::/64,GB,GB-SLG,London,SL1 4AX 1136 | 2a03:b0c0:1:d0::/64,GB,GB-SLG,London,SL1 4AX 1137 | 2a03:b0c0:1:e0::/64,GB,GB-SLG,London,SL1 4AX 1138 | 2a03:b0c0:2:d0::/64,NL,NL-NH,Amsterdam,1098 XH 1139 | 2a03:b0c0:2:f0::/64,NL,NL-NH,Amsterdam,1098 XH 1140 | 2a03:b0c0:3:d0::/64,DE,DE-HE,Frankfurt,60341 1141 | 2a03:b0c0:3:e0::/64,DE,DE-HE,Frankfurt,60341 1142 | 2a03:b0c0:3:f0::/64,DE,DE-HE,Frankfurt,60341 1143 | --------------------------------------------------------------------------------