{"id":42841165,"url":"https://github.com/kosmas-valianos/libproxyprotocol","last_synced_at":"2026-01-30T11:50:52.070Z","repository":{"id":42525984,"uuid":"467542492","full_name":"kosmas-valianos/libproxyprotocol","owner":"kosmas-valianos","description":"An ANSI C library to parse and create PROXY protocol v1 and v2 headers","archived":false,"fork":false,"pushed_at":"2025-04-01T12:48:30.000Z","size":156,"stargazers_count":11,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-01T13:26:01.684Z","etag":null,"topics":["ansi-c","aws-load-balancer","azure-loadbalancer","haproxy","load-balancer","proxy-protocol","shared-library","windows-dll"],"latest_commit_sha":null,"homepage":"https://www.proxy-protocol.com/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kosmas-valianos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-08T14:20:04.000Z","updated_at":"2025-03-09T07:49:56.000Z","dependencies_parsed_at":"2025-04-01T13:34:14.030Z","dependency_job_id":null,"html_url":"https://github.com/kosmas-valianos/libproxyprotocol","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/kosmas-valianos/libproxyprotocol","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosmas-valianos%2Flibproxyprotocol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosmas-valianos%2Flibproxyprotocol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosmas-valianos%2Flibproxyprotocol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosmas-valianos%2Flibproxyprotocol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kosmas-valianos","download_url":"https://codeload.github.com/kosmas-valianos/libproxyprotocol/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosmas-valianos%2Flibproxyprotocol/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28912077,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T08:15:08.179Z","status":"ssl_error","status_checked_at":"2026-01-30T08:14:31.507Z","response_time":66,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansi-c","aws-load-balancer","azure-loadbalancer","haproxy","load-balancer","proxy-protocol","shared-library","windows-dll"],"created_at":"2026-01-30T11:50:51.412Z","updated_at":"2026-01-30T11:50:52.066Z","avatar_url":"https://github.com/kosmas-valianos.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# libproxyprotocol\nAn ANSI C library to **parse** and **create** [PROXY protocol](https://www.haproxy.org/download/2.7/doc/proxy-protocol.txt) v1 and v2 headers with support for **all TLVs** including the custom ones from AWS and Azure\n* Full coverage of the latest specification.\n* Easy addition of any TLV through API functions when creating v2 PROXY protocol headers.\n* Easy access of the values of the extracted v2 TLVs through API functions. Moreover, in case the v2 TLV values are US-ASCII string names, they are given as proper NULL terminated strings for easy usage.\n* Easy way through the API to request a specific alignment, CRC32C checksum when creating v2 PROXY protocol headers.\n* Easy way through an API function to create health check v2 PROXY protocol headers.\n* Socket free logic. Does not hook, manipulate, assume any networking. It merely works on buffers.\n* Compilable with most compilers and usable at any platform as it is written in ANSI C.\n\n## Installation\nThe library should be compilable to any platform as it is written in ANSI C. It comes with a Makefile which can create the shared library `libproxyprotocol.so` which can then be linked to your application. Dynamic linking is the suggested way as it applies at all cases! You can link statically using the `.o` directly but keep in mind that in case of a commercial product you **must** use the shared library `.so`due to the LGPL restrictions. Special care has been taken to make it work with Windows as well. In that case you have to compile it to a .dll/.lib yourself. In case of Windows remember that you have to link with the `ws2_32.lib`. An example of this is shown in tests.\n\n## API/Usage\nAll the API details are in the proxy_protocol.h. The complete example for creating/parsing v1 and v2 PROXY protocol headers can be found at `examples/client_server.c`\n\n### Create a v1 PROXY protocol header\n```\npp_info_t pp_info_in_v1 = {\n        .address_family = ADDR_FAMILY_INET,\n        .transport_protocol = TRANSPORT_PROTOCOL_STREAM,\n        .src_addr = \"172.22.32.1\",\n        .dst_addr = \"172.22.33.1\",\n        .src_port = 4040,\n        .dst_port = 443\n    };\nuint16_t pp1_hdr_len;\nint32_t error;\nuint8_t *pp1_hdr = pp_create_hdr(1, \u0026pp_info_in_v1, \u0026pp1_hdr_len, \u0026error);\n/* Clear the pp_info passed in pp_create_hdr(). Not really needed for v1 but good to do out of principle */\npp_info_clear(\u0026pp_info_in_v1);\nif (error != ERR_NULL)\n{\n    fprintf(stderr, \"pp_create_hdr() failed: %s\", pp_strerror(error));\n    return EXIT_FAILURE;\n}\n```\n\n### Parse a v1 PROXY protocol header\n```\npp_info_t pp_info_out;\nint32_t rc = pp_parse_hdr(pp1_hdr, pp1_hdr_len, \u0026pp_info_out);\nfree(pp1_hdr);\nif (!rc)\n{\n    printf(\"Not a PROXY protocol header\\n\");\n}\nelse if (rc \u003c 0)\n{\n    fprintf(stderr, \"pp_parse_hdr() failed: %s\", pp_strerror(rc));\n    pp_info_clear(\u0026pp_info_out);\n    return EXIT_FAILURE;\n}\nelse\n{\n    printf(\"%d bytes PROXY protocol header: %s %s %hu %hu\\n\",\n        rc,\n        pp_info_out.src_addr, pp_info_out.dst_addr,\n        pp_info_out.src_port, pp_info_out.dst_port);\n}\n/* ALWAYS clear the pp_info after a call to pp_parse_hdr() */\npp_info_clear(\u0026pp_info_out);\n```\n```\n45 bytes PROXY protocol header: 172.22.32.1 172.22.33.1 4040 443\n```\n\n### Create a v2 PROXY protocol header\n```\npp_info_t pp_info_in_v2 = {\n    .address_family = ADDR_FAMILY_INET,\n    .transport_protocol = TRANSPORT_PROTOCOL_STREAM,\n    .src_addr = \"192.168.10.100\",\n    .dst_addr = \"192.168.11.90\",\n    .src_port = 42332,\n    .dst_port = 8080,\n    .pp2_info = {\n        .crc32c = 1,        /* Add crc32c checksum */\n        .pp2_ssl_info = {   /* Add SSL information */\n            .ssl = 1,\n            .cert_in_connection = 1,\n            .cert_in_session = 1,\n            .cert_verified = 1,\n        }\n    }\n};\n/* Add SSL TLVs */\n/* IMPORTANT: Always clear the pp_info to be passed in pp_create_hdr() because TLVs are allocated in heap. Otherwise memory will be leaked */\nif (!pp_info_add_ssl(\u0026pp_info_in_v2, \"TLSv1.2\", \"ECDHE-RSA-AES128-GCM-SHA256\", \"SHA256\", \"RSA2048\", \"example.com\", 11))\n{\n    fprintf(stderr, \"pp_info_add_ssl() failed\\n\");\n    pp_info_clear(\u0026pp_info_in_v2);\n    return EXIT_FAILURE;\n}\n/* Add Azure Link ID TLV */\nif (!pp_info_add_azure_linkid(\u0026pp_info_in_v2, 1234))\n{\n    fprintf(stderr, \"pp_info_add_azure_linkid() failed\\n\");\n    pp_info_clear(\u0026pp_info_in_v2);\n    return EXIT_FAILURE;\n}\nuint8_t *pp2_hdr = pp_create_hdr(2, \u0026pp_info_in_v2, \u0026pp2_hdr_len, \u0026error);\npp_info_clear(\u0026pp_info_in_v2);\nif (error != ERR_NULL)\n{\n    fprintf(stderr, \"pp_create_hdr() failed: %s\", pp_strerror(error));\n    return EXIT_FAILURE;\n}\n```\n\n### Parse a v2 PROXY protocol header\n```\nrc = pp_parse_hdr(pp2_hdr, pp2_hdr_len, \u0026pp_info_out);\nfree(pp2_hdr);\nif (!rc)\n{\n    printf(\"Not a PROXY protocol header\\n\");\n}\nelse if (rc \u003c 0)\n{\n    fprintf(stderr, \"pp_parse_hdr() failed: %s\", pp_strerror(rc));\n    pp_info_clear(\u0026pp_info_out);\n    return EXIT_FAILURE;\n}\nelse\n{\n    uint16_t length, cn_length;\n    const uint8_t *azure_linkid = pp_info_get_azure_linkid(\u0026pp_info_out, \u0026length);\n    uint32_t linkid;\n    memcpy(\u0026linkid, azure_linkid, length);\n    const uint8_t *cn = pp_info_get_ssl_cn(\u0026pp_info_out, \u0026cn_length);\n    printf(\"%d bytes PROXY protocol header:\\n\"\n            \"\\tAzure Link ID: %u\\n\"\n            \"\\tCRC32C checksum: %s\\n\"\n            \"\\tSSL version: %s\\n\"\n            \"\\tSSL cipher: %s\\n\"\n            \"\\tSSL sig_alg: %s\\n\"\n            \"\\tSSL key_alg: %s\\n\"\n            \"\\tSSL CN: %.*s\\n\"\n            \"%s %s %hu %hu\\n\",\n        rc, linkid,\n        /* In case CRC32c is wrong then rc \u003c 0 =\u003e pp_strerror(rc) at previous block will print the error */\n        pp_info_out.pp2_info.crc32c == 1 ? \"verified\" : \"not present\",\n        pp_info_get_ssl_version(\u0026pp_info_out, \u0026length),\n        pp_info_get_ssl_cipher(\u0026pp_info_out, \u0026length),\n        pp_info_get_ssl_sig_alg(\u0026pp_info_out, \u0026length),\n        pp_info_get_ssl_key_alg(\u0026pp_info_out, \u0026length),\n        cn_length, cn,\n        pp_info_out.src_addr, pp_info_out.dst_addr,\n        pp_info_out.src_port, pp_info_out.dst_port);\n}\n/* ALWAYS clear the pp_info after a call to pp_parse_hdr() */\npp_info_clear(\u0026pp_info_out);\n```\n```\n124 bytes PROXY protocol header:\n   Azure Link ID: 1234\n   CRC32C checksum: verified\n   SSL version: TLSv1.2\n   SSL cipher: ECDHE-RSA-AES128-GCM-SHA256\n   SSL sig_alg: SHA256\n   SSL key_alg: RSA2048\n   SSL CN: example.com\n   192.168.10.100 192.168.11.90 42332 8080\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkosmas-valianos%2Flibproxyprotocol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkosmas-valianos%2Flibproxyprotocol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkosmas-valianos%2Flibproxyprotocol/lists"}